GitHub
CERT Secure Coding

DRD20-C. Specify permissions when creating files via the NDK

(THIS CODING RULE OR GUIDELINE IS UNDER CONSTRUCTION)

When the standard methods of creating files in the Android SDK are used, the output files are created with the following permissions:

-rw-rw-r--

The result is a file that is world readable but not writable. If one were to instead create a file via the native development kit using the Java native interface and relied on the default permissions, the result would be a new file with the following permissions :

-rw-rw-rw-

This new file ends up being world readable and world writable because when native code is used to create files, the umask of the zygote process (which is set to 000) is inherited. Such relaxed permissions could potentially lead to security issues since the new file may be corrupted intentionally or otherwise by another application on the device if the file location is known [ Intrepidus 2012 ].

Noncompliant Code Example

In this noncompliant example, native C code is used to create a text file and write to it. However, this will result in a new file that is both world readable and writable.

Non-compliant code
FILE * fp = fopen("/data/data/com.mine.work/file.txt", "a");
fprintf(fp, "Don't alter this content.\n");
fclose(fp);

Compliant Solution (Set Umask)

In this compliant example, the user forces the permissions of the created file to match those of the SDK by changing the process's umask using the umask() C library call.

Compliant code
umask(002);
FILE * fp = fopen("/data/data/com.mine.work/file.txt", "a");
if (fp == NULL) {
  /* Handle error */
}
fprintf(fp, "Don't corrupt this content.\n");
fclose(fp);

Compliant Solution (Specify File Permissions)

In this compliant example, the user explicitly specifies the created file's permissions using the open() system call.

Compliant code
const char * fn = "/data/data/com.mine.work/file.txt";
const char * content = "Don't corrupt this content.\n";
int fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
if (fd == -1) {
  /* Handle error */
}
size_t len = strlen(content);
while (len > 0) {
  ssize_t written = write(fd, content, len);
  if (written == -1) {
    /* Handle error */
  }
  content += written;
  len -= written;
}
close(fd);

Risk Assessment

Allowing the default permissions when a file is created in native code may allow sensitive data to be revealed or corrupted.

Rule Severity Likelihood Detectable Repairable Priority Level
DRD20-C High Probable Yes No P12 L1

Automated Detection

Calls to the functions that create files can be detected automatically but it is not feasible to automatically check that file permissions have been applied appropriately.

Tool

Version

Checker

Description

Bibliography

[ Intrepidus 2012 ]