OS: Android L
Server: an native level system server, service through abstract socket.
Client: jni in normal 3rd APK
Get a 'permission denied' while using APK to connect the socket.
I thought abstract socket has no permissions!
And, the same code works when running in a adb shell, rooted shell.
The question is: where is the permisson set?
the code:
char *target_socket_name = "#mobilelogd";
int sock_id = 0;
struct sockaddr_un sun;
int address_len;
sock_id = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock_id < 0) {
LOG("in %s: Unable to create socket: %s\n", __func__, strerror(errno));
return -1;
} else {
LOG("socket created!\n");
}
memset(&sun, 0, sizeof(sun));
sun.sun_family = AF_UNIX;
strncpy(sun.sun_path, target_socket_name, strlen(target_socket_name));
sun.sun_path[0] = 0;
address_len = offsetof(struct sockaddr_un, sun_path) + strlen(target_socket_name);
if (connect(sock_id, (struct sockaddr *)&sun, address_len) == -1)
{
LOG("in %s: Connect to socket failed: (%d),%s\n", __func__, errno, strerror(errno));
close(sock_id);
return -1;
}
--- EDIT 1 ---: add some initialise code,and change '0' to 0. Same result.
Okay, here is the scoop it changed on L by a bug introduced..the bug fix is the pipeline:
https://android.googlesource.com/device/moto/shamu/+/b2db40f
Until than do java pipes or native pipes instead
Since Android manipulated the Linux kernel and added Paranoid networking to it, So you should add the following permission to your manifest file.
<uses-permission android:name="android.permission.INTERNET" />
Android adds a "paranoid network" option to the Linux kernel, which restricts access to some networking features depending on the group of the calling process.
So, your app's uid (user id; each app is assigned an unique uid once it is installed) must be granted that permission in order to do networking tasks.
Related
I need to send few strings on localhost via socket on android using native code (in C particularity) but I've faced weird problem - recv() function always returns -1 and eerno tells "Try again!"
Here is code responsible for initialization of socket and receiving response
void request() {
struct sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
//need to send string to localhost
inet_aton("127.0.0.1", &(sa.sin_addr));
int sock;
char res[7];
sock = socket(AF_INET, SOCK_STREAM, 0);
sa.sin_port = htons(27042);
int connection = connect(sock, (struct sockaddr *) &sa, sizeof sa);
if (connection != -1) { //connection >= 0
memset(res, 0, 7);
send(sock, "\x00", 1, NULL);
send(sock, "AUTH\r\n", 6, NULL);
usleep(100); // Give it some time to answer
int rec = recv(sock, res, 7, MSG_DONTWAIT);
// rec is always -1 and errno says "Try again!"
}
close(sock);
}
There is an INTERNET permission in Manifest file.
I've tried to put recv(sock, res, 7, MSG_DONTWAIT) part in while loop to wait maybe it would return some data but no success. Maybe I need to call something like flush() after send()?
Does any one know where could be trouble?
UPD. This code runs in one android app (client) and tries to send string to other android app that runs on the same device (server).
Solution became pretty obvious - current "server" version can't process "AUTH" message that is why "client" app receive -1 response. I've tried older version and everything worked fine.
I am developing an app in C for Android. I want to add a new tun interface and use the file descriptor to access the device. The way I am doing it is the same as described here: https://backreference.org/2010/03/26/tuntap-interface-tutorial/
However, I am getting Operation not permitted on ioctl() call. My device is rooted, I granted superuser rights to my app, set SELinux policy to permissive. But still, Android does not allow me to access /dev/net/tun. I created it by creating symbolic link from /dev/tun. I also didn't forget to set chmod 666 on /dev/tun. Calling open("/dev/net/tun", O_RDWR | O_NONBLOCK) returns a valid file descriptor, and I set the ifreq struct correctly. It is exactly ioctl() call that returns an error that is Operation not permitted.
Furthermore, if I separate the code and cross-compile it, and then push it to device via adb and run it - everything works. But if I do it as a part of my application, the Operation is not permitted.
Any advise on how to allow this system call inside application? Any tips on why it fails would be also appreciated.
Code:
int create_virtual_nic(char *device) {
struct ifreq ifr;
int fd_tunnel = -1;
int err = -1;
fd_tunnel = open("/dev/net/tun", O_RDWR | O_NONBLOCK);
if(fd_tunnel < 0) {
fprintf(stderr, "Could not open TUN device!\n");
return fd_tunnel;
}
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
if (*device) {
strncpy(ifr.ifr_name, device, IFNAMSIZ);
}
// ERROR IS HERE
err = ioctl(fd_tunnel, TUNSETIFF, (void*) &ifr);
if(err < 0 ) {
close(fd_tunnel);
perror("ioctl()");
fprintf(stderr, "Device '%s' taken or not running as root!\n", device);
exit(EXIT_FAILURE);
} else {
fprintf(stdout, "Succesfullt ioctl() on %d\n", err);
}
fprintf(stdout, "Created interface '%s'...\n", device);
return fd_tunnel;
}
I have problems with client/server application that is part of a bigger system for distributed computing. The clients are Android devices that run a native Android NDK application written in C. At some point the clients send registration messages to the server application, which is also written in C and runs on a windows machine.
The weird thing is, right after installing the Android application on the device everything works fine. However, after a while the Socket problem starts. All connect() function calls end with a time out on the client side. The error is not deterministic and occurs at different points in time. To make it work again, I have to uninstall the application in Android manually and reinstall it. After that I works for some time and then the error starts again. The same C code is used on clients that run on normal windows PCs and there the problem does not occur.
The network connection is fine and I checked, if the server ports are open and reachable with the Simple Socket Tester app from the client device. I also gave Android the permission for Internet use and the parameters of the connect() call are correct.
EDIT:
Sorry for the missing code. I thought the error is obvious and based on the different platforms, since it works on windows and I am not that experienced in Android NDK. Here is the code:
int pi_connect(SOCKET s, const SOCKADDR *name, int namelen)
{
int result = connect(s, name, namelen);
if (result < 0) {
ALOG("Socket connecting error!");
return -1;
}
return result;
}
SOCKET pi_socket(int af, int type, int protocol) {
SOCKET returnSocket = socket(af, type, protocol);
int yes = 1;
if (setsockopt(returnSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
perror("Server-setsockopt() error!");
exit(1);
}
if (returnSocket < 0) {
ALOG("Socket creation error!");
return -1;
}
return returnSocket;
}
SOCKET setupSendSocket(u_long host, int hostPort) {
SOCKET sendingSocket;
SOCKADDR_IN addr;
sendingSocket = pi_socket(AF_INET, SOCK_STREAM, 0);
memset(&addr, 0, sizeof(SOCKADDR_IN));
addr.sin_family = AF_INET;
addr.sin_port = htons(hostPort);
addr.sin_addr.s_addr = host;
long rc = pi_connect(sendingSocket, (SOCKADDR*) &addr, sizeof(SOCKADDR));
if (rc < 0) {
return 0;
}
return sendingSocket;
}
void requestOwnIP() {
SOCKET connectedIPSocket = setupSendSocket(inet_addr(brokerIP), 34123);
if(connectedIPSocket==0)
return;
sendBHeartbeatMessage(connectedIPSocket);
myIP = receiveBIPMessage(connectedIPSocket);
pi_closesocket(connectedIPSocket);
}
The requestOwnIP() function is called in the main function of the NDK application.
EDIT 2 (some new remarks): After rebooting the device, the connect() is successful again and the system works for some time. Is there something stored in the process table of the operating system, that can cause this problem? I first though that it could be a high amount of sockets that are in the time_wait state, but I added SO_REUSEADDR and the problem is still occurring.
I would really appreciate some help. Thank you in advance!
Regards
Dominik
I have made an executable binary built through android ndk. I put the binary in /data/local/tmp.
In the binary I try to bind a socket which I later on want to listen through my android app. I have got root permissions still the bind shows 30 as error which means read only file system. Can anyone tell me what else do I need to do bind a socket?
My code in brief:
int serv_sock = -1, len;
struct sockaddr_un serv_soc_addr;
if ((serv_sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
printf( "socket error:%d\n", errno);
return -1; // Terminatie DR
}
bzero(&serv_soc_addr, sizeof(serv_soc_addr));
serv_soc_addr.sun_family = AF_UNIX;
strcpy(serv_soc_addr.sun_path, "iptable_socket");
unlink(serv_soc_addr.sun_path);
len = strlen(serv_soc_addr.sun_path) + sizeof(serv_soc_addr.sun_family);
if (0 != bind(serv_sock, (struct sockaddr*) &serv_soc_addr, len)) {
printf( "bind error:%d\n", errno);
close(serv_sock);
return -1; //Terminate DR
}
root#android:/ # /data/local/tmp/hello-jni
bind error:30
I was able to solve this one myself. Probably someone else looking for this might find helpful.
I changed the type of socket from Abstract type to FileSystem type.
I put the unlink statement at the end of the function after the accept system call breaks rather than just after strcpy as above.
Lastly I ran chmod on my binary.
Any other pointers would be helpful. Thanks.
I'm having some troubles with the Android NDK.
My project requires software components written in C that can receive data over TCP to be executed on the Android OS.
To that end, I've made a simple server and client in C using BSD sockets and can send messages back and forth successfully across the connection on PCs. Now I've moved the clientside code into the NDK, and can't connect to my server from the emulator or from an actual android device. NDK compiles without warnings or errors, the emulator/phone are on wifi and have internet permissions enabled in the manifest. What gives?
All it does is make a socket, fill in host/port info and attempt to connect: If it does connect, send a message, else return an error. Android always returns a negative value for connect
This client code, compiled/executed on Mac/Windows/Linux, works:
PC Client code:
int tcp_socket = socket(AF_INET, SOCK_STREAM,0);
if(tcp_socket< 0 ) {
cerr << "Failed to create TCP socket." << endl;
return 2;
}
sockaddr_in server_tcp_add;
server_tcp_add.sin_family = AF_INET;
server_tcp_add.sin_port = htons(tcp_port); //set via command line: Yes, they are the same for the android
hostent *hostp = gethostbyname(server_host);
memcpy(&server_tcp_add.sin_addr, hostp->h_addr, hostp->h_length);
socklen_t slen = sizeof(server_tcp_add);
if(connect(tcp_socket,(sockaddr*)&server_tcp_add, slen) <0 ){
cerr<< "Failed to connect to server with TCP. " << endl;
close(tcp_socket);
return 3;
}
char* myString = "This is my message";
send(tcp_socket, myString, strlen(myString), 0);
close(tcp_socket);
This code, executed on the Android NDK, does not
Code: NDK Client
jstring Java_networking_client_activate_initiateTcpConnection(JNIEnv* env, jobject javaThis){
int tcp_socket = socket(AF_INET, SOCK_STREAM,0);
if(tcp_socket < 0){
return (*env)->NewStringUTF(env, "ERROR CREATING SOCKET");
}
const char* server_host = "some.numbers.that.work"; //It's a valid IP I don't feel like sharing
unsigned short server_port = 43000;
struct sockaddr_in server_tcp_addr;
server_tcp_addr.sin_family = AF_INET;
server_tcp_addr.sin_port = htons(server_port);
struct hostent *hostp = gethostbyname(server_host);
memcpy(&server_tcp_addr, hostp->h_addr, hostp->h_length);
socklen_t slen = sizeof(server_tcp_addr);
if(connect(tcp_socket,(struct sockaddr*)&server_tcp_addr, slen) < 0){ //fails here
close(tcp_socket);
return (*env)->NewStringUTF(env, "ERROR CONNECTING TO SERVER");
}
char* message = "hello from android!";
send(tcp_socket, &message, sizeof(message),0);
return (*env)->NewStringUTF(env, "TCP message sent!");
}
Largely identical; required to put struct in front of everything for NDK to compile.
--edit--I should also mention, I have been able to send data over sockets in Java with this app. Just the C sockets that's really screwing stuff up. Even a sample of someone else that has C sockets working via NDK would be tremendously appreciated.
This is a very late answer, however it might still be useful...
I changed this line:
memcpy(&server_tcp_addr, hostp->h_addr, hostp->h_length);
to this:
memcpy(&server_tcp_addr.sin_addr.s_addr, hostp->h_addr, hostp->h_length);
and that did the trick for me.