0

I am working at an Android app that, among other things, must send background data to a ftp server. The code that does this is written in native code, using standard Linux functions.

Most of the time it works fine, but every once in a while it crashes, and the crash drives me crazy, because it makes no sense to me.

Here is the relevant code:


 if(!sbuf.st_size)
 {
     syslog(LOG_CRIT, "FTP: OMFG WE GOT 0 FILE SIZE!!!11!!!! ");
     close(fd);
     fclose(stream);
     close(dsock);
     return 0;
 }

 p = mmap(0, (size_t) sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);

 if(p==MAP_FAILED)
 {
     syslog(LOG_CRIT, "FTP: We got a mmap problem.... %s",strerror(errno));
     close(fd);
     fclose(stream);
     close(dsock);
     return 0;
 }

 syslog(LOG_CRIT, "Before fwrite");

 if(fwrite(p, 1, (size_t) sbuf.st_size, stream)!=(size_t) sbuf.st_size)
 {
     syslog(LOG_CRIT, "FTP: We got a fwrite problem.... %s",strerror(errno));
     munmap(p, (size_t) sbuf.st_size);
     close(fd);
     fclose(stream);
     close(dsock);
     return 0;
 }

 fflush(stream);
 usleep(150000);
 syslog(LOG_CRIT, "Before munmap");

 munmap(p, (size_t) sbuf.st_size);
 //fflush(stream);
 close(fd);
 fclose(stream);
 close(dsock);

 int tries=0;

 while(1) {

     if(tries>3)return 0;

     len = ftpTryRead(csock, buffer, 128);
     if (len <= 0) {
         syslog(LOG_CRIT, "FTP: Got null after upload, len is %i",len);
         //return 0;
         usleep(300000);
         tries++;
         continue;
     }

     if(!strncmp(buffer,"226",3))break;
     else
     {
         syslog(LOG_CRIT, "FTP: Expected 226 but got %s",buffer);
         return 0;
     }
 }
 //sleep(2);

 syslog(LOG_CRIT, "FTP: Uploading of file %s should be completed.",file);
 unlink(file_name);
 
 return 1;

The relevant stuff in the logcat is this:

07-13 21:30:50.557 10268-10376/? E/com.example.ftp_cam: Before munmap
07-13 21:30:50.561 10268-15934/? E/IMemory: cannot dup fd=69, size=4096, err=0 (Bad file descriptor)
07-13 21:30:50.561 10268-15934/? E/IMemory: cannot map BpMemoryHeap (binder=0x7f57d239a0), size=4096, fd=-1 (Bad file descriptor)
07-13 21:30:50.561 10268-15934/? A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 15934 (Binder:10268_6)
07-13 21:30:50.570 10268-10376/? E/com.example.ftp_cam: FTP: Uploading of file IMG_20200713_082444.jpg should be completed.

So it seems that the code crashes in munmap. However, the code continues for a bit after the segfault, because it shows the file upload completed message (which is further down the code).

Any idea what might the problem be? Thanks for your time!

Radu
  • 923
  • 2
  • 9
  • 21

2 Answers2

3

So it seems that the code crashes in munmap.

If I understand the logfile correctly, this is not the case:

Your program seems to be multi-threaded (in the case of the log file: threads 10376 and 15934).

You call munmap() from thread 10376 but your program is crashing in thread 15934.

So the problem lies in the other thread. Maybe it does not have to do with the munmap() at all.

However, it may have to do with the munmap(): Maybe the other thread accesses the memory mapped...

Martin Rosenau
  • 17,897
  • 3
  • 19
  • 38
  • Hmm, good catch. I do have some other threads, but they do not interact with this thread or its variables. One is a web server listening for stuff (but that spends the time in an accept() and I don't issue any commands to it), and another is an alarm thread that mostly sleeps and sometimes sets a variable to 1. Then there is the main (Java) thread which just takes pictures. – Radu Jul 13 '20 at 19:28
-2

You are mapping fd with PROT_READ and trying to write to it. The write will kill your application. Also, in order to write to addresses you don't use functions like fwrite(), you could simply set address to something or use memset, strcpy etc.

Ady
  • 52
  • 1
  • I am not reading to it, I am reading from it, to a stream. – Radu Jul 13 '20 at 14:39
  • p = mmap(0, (size_t) sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if(fwrite(p, 1, (size_t) sbuf.st_size, stream)!=(size_t) sbuf.st_size) – Ady Jul 13 '20 at 14:56
  • This answer is completely wrong. That reads from `p` and writes to `stream`. – Joseph Sible-Reinstate Monica Jul 13 '20 at 15:20
  • sorry you are right. Usually the first argument for write functions is an fd but fwrite() is special. Anyway, what is your fd? If your fd in some case is -1 then your mmap will fail and latter you are doing a close(-1). Not sure what will happen then. – Ady Jul 13 '20 at 15:53
  • from the crash logs, the sequence looks like: dup(fd) -> failed, mmap(fd) -> failed, something somewhere else in libc got seg fault. – Ady Jul 13 '20 at 16:02
  • I am checking for FD earlier in the code. Also, according to the logs, the error happens after the mmap and fwrite, so if it's a mmap problem it should appear sooner (and possibly return an error). – Radu Jul 13 '20 at 16:08
  • Yes correct. But what are you doing after mmap,fwrite and munmap? I assume you are calling the same code again? If not then it is crashing somewhere else but not in the code snippet you wrote here. – Ady Jul 13 '20 at 16:22
  • I am calling that code again, but there are many syslogs until then, so the crash is in between before munmap and the end of the function. I don't see where it would crash after the munmap, but I will edit the original question to include the code after as well. – Radu Jul 13 '20 at 16:36
  • What do you do in the ftpTryRead()? Did dmesg tells you something? I think something in your app is creating problem for the Binder which will eventually crash when it can't create heap anymore. – Ady Jul 14 '20 at 08:29
  • ftpTryRead is a small function, it has a select() and read() (and no, there are no buffer over/under runs in there). – Radu Jul 14 '20 at 20:22
  • Which Android version are you using? – Ady Jul 15 '20 at 11:35
  • I am using Android 6, on a Xiaomi Note 4 – Radu Jul 15 '20 at 14:33
  • Android 8 will fix your problem for sure. – Ady Jul 15 '20 at 22:01