c - setuid program doesn't work on 2.6 kernel -
i having trouble understanding why setuid program doesn't seem elevating permissions, though id's seem correct. running on 2.6 kernel , fails, works intended on ubuntu 14.04 doing same thing. need program @ times during execution needs elevated permissions, while least privilege default.
#include <stdio.h> #include <stdint.h> #include <arpa/inet.h> #include <stdint.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> static uid_t _orig_euid; void save_privilege(void){ _orig_euid = geteuid(); printf("saved privilege: %d\n", _orig_euid); } void drop_privileges(void){ if(seteuid(getuid()) == -1){ exit(0); } printf("dropped privileges %d %d\n", getuid(), geteuid()); } void reacquire_privileges(void){ if(setuid(_orig_euid) == -1){ exit(0); } printf("reacquired privileges %d %d\n", getuid(), geteuid()); } void do_privileged(int rw){ switch(rw){ case 0: //read driver system("dd if=/dev/myrandom bs=10 count=1"); case 1: //write driver system("dd if=/dev/zero of=/dev/myrandom"); case 2: //change in proc fs system("echo 3 > /proc/sys/vm/drop_caches"); default: break; } } int main(int argc, char *argv[]){ int i; if(argc != 2){ printf("usage: %s testno\n", argv[0]); return 0; } = atoi(argv[1]); save_privilege(); do_privileged(i); drop_privileges(); do_privileged(i); reacquire_privileges(); do_privileged(i); return 0; }
my program permissions set as:
ls -l -rwsr-xr-x 1 root root 6547 sep 13 00:35 test
my current user id is:
id uid=1000(user) gid=1000(user)
the procfs entry i'm trying write is:
ls -l /proc/sys/vm/drop_caches -rw-r--r-- 1 root root 0 sep 13 00:36 /proc/sys/vm/drop_caches
when run program, get:
./test 2 saved privilege: 0 sh: cannot create /proc/sys/vm/drop_caches: permission denied dropped privileges 1000 1000 sh: cannot create /proc/sys/vm/drop_caches: permission denied reacquired privileges 1000 0 sh: cannot create /proc/sys/vm/drop_caches: permission denied
however, running same program on ubuntu 14.04 works correctly - fails modify procfs entry when privileges dropped.
here strace (./test_perm same ./test).
$ strace ./test_perm 2 execve("./test_perm", ["./test_perm", "2"], [/* 8 vars */]) = 0 mmap2(null, 4096, prot_read|prot_write, map_private|map_anonymous|0x4000000, -1, 0) = 0x40005000 open("/lib/libc.so.0", o_rdonly) = 3 fstat(3, {st_mode=s_ifreg|0755, st_size=310348, ...}) = 0 mmap2(null, 4096, prot_read|prot_write, map_private|map_anonymous|0x4000000, -1, 0) = 0x40006000 read(3, "\177elf\1\1\1\0\0\0\0\0\0\0\0\0\3\0(\0\1\0\0\0\260\256\0\0004\0\0\0"..., 4096) = 4096 mmap2(null, 360448, prot_none, map_private|map_anonymous, -1, 0) = 0x4000e000 mmap2(0x4000e000, 303968, prot_read|prot_exec, map_private|map_fixed, 3, 0) = 0x4000e000 mmap2(0x40060000, 4972, prot_read|prot_write, map_private|map_fixed, 3, 0x4a) = 0x40060000 mmap2(0x40062000, 15112, prot_read|prot_write, map_private|map_fixed|map_anonymous, -1, 0) = 0x40062000 close(3) = 0 munmap(0x40006000, 4096) = 0 stat("/lib/ld-uclibc.so.0", {st_mode=s_ifreg|0755, st_size=21200, ...}) = 0 mprotect(0x40060000, 4096, prot_read) = 0 mprotect(0x4000c000, 4096, prot_read) = 0 ioctl(0, sndctl_tmr_timebase or tcgets, {b38400 opost isig icanon echo ...}) = 0 ioctl(1, sndctl_tmr_timebase or tcgets, {b38400 opost isig icanon echo ...}) = 0 geteuid32() = 1000 write(1, "saved privilege: 1000\n", 22saved privilege: 1000 ) = 22 rt_sigaction(sigquit, {sig_ign, [quit], sa_restart|0x4000000}, {sig_dfl, [], 0}, 8) = 0 rt_sigaction(sigint, {sig_ign, [int], sa_restart|0x4000000}, {sig_dfl, [], 0}, 8) = 0 rt_sigaction(sigchld, {sig_dfl, [chld], sa_restart|0x4000000}, {sig_dfl, [], 0}, 8) = 0 vfork(sh: cannot create /proc/sys/vm/drop_caches: permission denied ) = 1183 --- sigchld (child exited) @ 0 (0) --- rt_sigaction(sigquit, {sig_ign, [quit], sa_restart|0x4000000}, {sig_ign, [quit], sa_restart|0x4000000}, 8) = 0 rt_sigaction(sigint, {sig_ign, [int], sa_restart|0x4000000}, {sig_ign, [int], sa_restart|0x4000000}, 8) = 0 wait4(1183, [{wifexited(s) && wexitstatus(s) == 2}], 0, null) = 1183 rt_sigaction(sigquit, {sig_dfl, [quit], sa_restart|0x4000000}, {sig_ign, [quit], sa_restart|0x4000000}, 8) = 0 rt_sigaction(sigint, {sig_dfl, [int], sa_restart|0x4000000}, {sig_ign, [int], sa_restart|0x4000000}, 8) = 0 rt_sigaction(sigchld, {sig_dfl, [chld], sa_restart|0x4000000}, {sig_dfl, [chld], sa_restart|0x4000000}, 8) = 0 getuid32() = 1000 setresuid32(-1, 1000, -1) = 0 getuid32() = 1000 geteuid32() = 1000 write(1, "dropped privileges 1000 1000\n", 29dropped privileges 1000 1000 ) = 29 rt_sigaction(sigquit, {sig_ign, [quit], sa_restart|0x4000000}, {sig_dfl, [quit], sa_restart|0x4000000}, 8) = 0 rt_sigaction(sigint, {sig_ign, [int], sa_restart|0x4000000}, {sig_dfl, [int], sa_restart|0x4000000}, 8) = 0 rt_sigaction(sigchld, {sig_dfl, [chld], sa_restart|0x4000000}, {sig_dfl, [chld], sa_restart|0x4000000}, 8) = 0 vfork(sh: cannot create /proc/sys/vm/drop_caches: permission denied ) = 1184 --- sigchld (child exited) @ 0 (0) --- rt_sigaction(sigquit, {sig_ign, [quit], sa_restart|0x4000000}, {sig_ign, [quit], sa_restart|0x4000000}, 8) = 0 rt_sigaction(sigint, {sig_ign, [int], sa_restart|0x4000000}, {sig_ign, [int], sa_restart|0x4000000}, 8) = 0 wait4(1184, [{wifexited(s) && wexitstatus(s) == 2}], 0, null) = 1184 rt_sigaction(sigquit, {sig_dfl, [quit], sa_restart|0x4000000}, {sig_ign, [quit], sa_restart|0x4000000}, 8) = 0 rt_sigaction(sigint, {sig_dfl, [int], sa_restart|0x4000000}, {sig_ign, [int], sa_restart|0x4000000}, 8) = 0 rt_sigaction(sigchld, {sig_dfl, [chld], sa_restart|0x4000000}, {sig_dfl, [chld], sa_restart|0x4000000}, 8) = 0 setuid32(1000) = 0 getuid32() = 1000 geteuid32() = 1000 write(1, "reacquired privileges 1000 1000\n", 32reacquired privileges 1000 1000 ) = 32 rt_sigaction(sigquit, {sig_ign, [quit], sa_restart|0x4000000}, {sig_dfl, [quit], sa_restart|0x4000000}, 8) = 0 rt_sigaction(sigint, {sig_ign, [int], sa_restart|0x4000000}, {sig_dfl, [int], sa_restart|0x4000000}, 8) = 0 rt_sigaction(sigchld, {sig_dfl, [chld], sa_restart|0x4000000}, {sig_dfl, [chld], sa_restart|0x4000000}, 8) = 0 vfork(sh: cannot create /proc/sys/vm/drop_caches: permission denied ) = 1185 --- sigchld (child exited) @ 0 (0) --- rt_sigaction(sigquit, {sig_ign, [quit], sa_restart|0x4000000}, {sig_ign, [quit], sa_restart|0x4000000}, 8) = 0 rt_sigaction(sigint, {sig_ign, [int], sa_restart|0x4000000}, {sig_ign, [int], sa_restart|0x4000000}, 8) = 0 wait4(1185, [{wifexited(s) && wexitstatus(s) == 2}], 0, null) = 1185 rt_sigaction(sigquit, {sig_dfl, [quit], sa_restart|0x4000000}, {sig_ign, [quit], sa_restart|0x4000000}, 8) = 0 rt_sigaction(sigint, {sig_dfl, [int], sa_restart|0x4000000}, {sig_ign, [int], sa_restart|0x4000000}, 8) = 0 rt_sigaction(sigchld, {sig_dfl, [chld], sa_restart|0x4000000}, {sig_dfl, [chld], sa_restart|0x4000000}, 8) = 0 exit(0) = ?
calling program under strace caused setuid bit ignored.
you tried run setuid binaries ruid == calling user's id. not work well; not seem main problem either.
don't ever call system() setuid program else shell=/tmp/evil your_setuid_program
, has root breakfast.
i hesitate want figure out you're doing wrong here that's causing setuid bit not work because have no idea how write setuid binaries.
Comments
Post a Comment