/* ** Issue as discovered by richard lucassen in ** ** After setuid, open returns "permission denied" when trying to ** open /dev/stdder (which symlinks to /proc/self/fd/2). */ #include #include #include #include #include #include int open_file(char *pathname, char *msg); int main(int argc, char *argv[]) { if (argc != 2) { fprintf(stderr, "usage: self_fd /dev/stderr\n"); /* Or, you could try some other file :-) */ exit(1); } /* Check we are who we need to be */ if (getuid() != 0) { fprintf(stderr, "I insist that I be run as root\n"); exit(1); } open_file(argv[1], "root"); /* Set ourselves to an arbitrary user id, group first */ if (setgid(500) == -1) { perror("setgid(500)"); exit(1); } if (setuid(500) == -1) { perror("setuid(500)"); exit(1); } open_file(argv[1], "uid 500"); return 0; } int open_file(char *pathname, char *msg) { int fd; char m[80]; struct stat s; fd = open(pathname, O_WRONLY); if (fd == -1) { snprintf(m, sizeof m, "open(%s) as %s", pathname, msg); perror(m); if (stat(pathname, &s) == -1) { snprintf(m, sizeof m, "stat(%s) as %s", pathname, msg); perror(m); } else { fprintf(stderr, "%s: uid: %u, gid: %u\n", pathname, s.st_uid, s.st_gid); } return 1; } else { if (fstat(fd, &s) == -1) { snprintf(m, sizeof m, "fstat(%s) as %s", pathname, msg); perror(m); } else { fprintf(stderr, "%s: uid: %u, gid: %u\n", pathname, s.st_uid, s.st_gid); } close(fd); return 0; } }