Effective UID doesn't behave as expected - c

Code
I wrote the following c program to print the real and effective uid:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
void main() {
printf("real uid: %d\n", (int) getuid());
printf("effective uid: %d\n", (int) geteuid());
}
I compiled it using gcc:
jazz#kryptonite beyond_basics $ gcc -o uid_demo.out uid_demo.c
Afterwards I changed owner and permissions as following:
jazz#kryptonite beyond_basics $ sudo chown root:root uid_demo.out
jazz#kryptonite beyond_basics $ sudo chmod u+s uid_demo.out
Result
Now I got:
jazz#kryptonite beyond_basics $ ll uid_demo.out
-rwsr-xr-x 1 root root 8712 Sep 8 18:12 uid_demo.out*
When running the program I get the following result:
jazz#kryptonite beyond_basics $ ./uid_demo.out
real uid: 1000
effective uid: 1000
Question
I would expect the effective uid to be 0.
Can anyone explain why it is not?
Thanks

It is surprising, isn't it?
It's worth checking the mount options on your filesystem - it may have been mounted with the nosuid option. To inspect the options, try running the mount command, or cat /proc/mounts.
(I'm sure you know which filesystem you are in, but for completeness, if you are cd'ed there, as per your example, you can use df . )

Related

C cannot endors another user permissions using setresuid

I wrote the following code expecting to spawn a /bin/sh from another user.
#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char **argv, char **envp)
{
setresgid(getegid(), getegid(), getegid());
setresuid(geteuid(), geteuid(), geteuid());
execve("/bin/sh", argv, envp);
return 0;
}
I then changed the owner to match with my target user and changed permissions (too much, I know)
chown usertarget:globalgroup ./shell
chmod 777 ./shell
chmod +s ./shell
ls -lah shell
Everything is fine according to me. However, It keeps opening a shell as my current user, not the target one.
I already tried to hardcode the userid of my target user and a few other things (setuid function, ...) but nothing seems to work...
Anyone has an idea or anything that could help me investigate this problem ?
EDIT #1
baseuser#machine:/tmp/tata$ ls -lah shell2
-rwsrwsrwx 1 targetuser globalgroup 7.2K Aug 18 18:21 shell2
baseuser#machine:/tmp/tata$ id
uid=1507(baseuser) gid=1314(globalgroup) groups=1314(globalgroup),100(users)
baseuser#machine:/tmp/tata$ ls -lah shell2
-rwsrwsrwx 1 targetuser globalgroup 7.2K Aug 18 18:21 shell2
baseuser#machine:/tmp/tata$ ./shell2
====== WELCOME USER ======
baseuser#machine:/tmp/tata$ id -a
uid=1507(baseuser) gid=1314(globalgroup) groups=1314(globalgroup),100(users)
baseuser#machine:/tmp/tata$
Well in facts, the parition was mounted with nosuid option. This can be checked through mount command

Why is effective UID still not 0?

So I got this code below from here. However when I follow the commands:
sudo chown root:root a.out
sudo chmod u+s a.out
It still won't run with effective uid to 0.
This is the code:
#define _POSIX_C_SOURCE 200112L // Needed with glibc (e.g., linux).
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void report (uid_t real) {
printf ("Real UID: %d Effective UID: %d\n", real, geteuid());
}
int main (void) {
uid_t real = getuid();
report(real);
seteuid(real);
report(real);
return 0;
}
The output is:
Real UID: 1000 Effective UID: 1000
Real UID: 1000 Effective UID: 1000
Where I supposed it should have been:
Real UID: 1000 Effective UID: 0
Real UID: 1000 Effective UID: 1000
The getuid function returns the real user id only. The real user id of user process is still 1000. The 1000 is stored in the real variable.
So, while calling of seteuid function you again sets the 1000 as the effective user id.But actually you have to set the 0 in that place. So only the effective user id doesn't changed.
Try the below it will works fine.
#define _POSIX_C_SOURCE 200112L // Needed with glibc (e.g., linux).
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void report (uid_t real) {
printf ("Real UID: %d Effective UID: %d\n", real, geteuid());
}
int main (void) {
uid_t real = getuid();
report(real);
seteuid(0);
report(real);
return 0;
}
Apparently as #MarkPlotnick said.
cd to the directory where that a.out is. Run df . to get the mount
point. Run mount | grep themountpoint and see what the filesystem type
and mount options are.
If there is something saying nosuid then you need to remount that part of filesystem without the nosuid flag.
This website here gives a good explanation about how to do that.

setuid() returns 0 but has no effect

I have the following code:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void main(int argc, char* argv[]) {
printf("uid=%u euid=%u\n", getuid(), geteuid());
printf("%d = setuid(euid)\n", setuid(geteuid()));
printf("uid=%u euid=%u\n", getuid(), geteuid());
}
Compiled and run this way:
val#particle:/tmp $ sudo gcc foo.c
val#particle:/tmp $ sudo chown dev-misc:dev-misc a.out
val#particle:/tmp $ sudo chmod u+s a.out
val#particle:/tmp $ ./a.out
uid=1000 euid=1006
0 = setuid(euid)
uid=1000 euid=1006
Why does the uid remain unchanged? And why does setuid report success? (according to the man page, 0 means success)
setuid() sets the effective user ID, not the real process ID. From the manual:
setuid() sets the effective user ID of the calling process. If the
effective UID of the caller is root (more precisely: if the caller
has the CAP_SETUID capability), the real UID and saved set-user-ID
are also set.
To be able to change real user ID, the process must have effective user ID set to 0. Since, it's not the case in your example, it doesn't change. setuid() succeeds because you are just setting it to the same effective user ID the process already has.

how to use settimeofday(2)?

What am I doing wrong here? I expect settimeofday() to change the system time, not return EINVAL.
$ uname -a
Linux io 4.3.5-300.fc23.x86_64 #1 SMP Mon Feb 1 03:18:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
$ cat settimeofday.c
#include <sys/time.h>
#include <stdio.h>
int main()
{
struct timeval tv = {0, 0};
if (settimeofday(&tv, 0) == -1)
perror("settimeofday");
}
$ gcc settimeofday.c
$ sudo ./a.out
settimeofday: Invalid argument
The error is coming from a Thinkpad T450 running Fedora 23. The same code runs fine on OS X.
EDIT
To clarify, the command is being executed as root:
# whoami
root
# sudo ./a.out
settimeofday: Invalid argument
As expected, I get EPERM not EINVAL if I run the program as a regular user:
$ ./a.out
settimeofday: Operation not permitted
Commit e1d7ba was introduced to the Linux kernel in mid-2015 and restricts the value of the tv_sec field. The restriction is influenced by system uptime -- see the commit message and related LKML discussion for details.
That's what was causing the settimeofday call to return EINVAL and explains why the code runs on OS X and older Linux machines.
As shown in the manpage of settimeofday().
If either tv or tz is NULL, the corresponding structure is not set or returned.

unsuccessfully call external shell script as non-root user

I want A user to do some jobs as B user. It's OK if B is root, but non-root user failed. Here are basic codes:
root.c:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
setuid( 0 );
system( "/tmp/script_of_root.sh" );
return 0;
}
script_of_root.sh:
#!/bin/sh
echo $RANDOM >> /tmp/file_of_root
playback:
$ cd /tmp
$ cc root.c -o root
$ su -
# chown root.root /tmp/root
# chmod 4755 /tmp/root
# exit
$ ./root
After executing "./root", file "/tmp/file_of_root" will be updated. But if I apply the same thing to a non-root user, it doesn't work. Codes:
foobar.c:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
setuid( 1001 ); // uid of user "foobar"
system( "/tmp/script_of_foobar.sh" );
return 0;
}
script_of_foobar.sh:
#!/bin/sh
echo $RANDOM >> /tmp/file_of_foobar
playback:
$ cd /tmp
$ cc foobar.c -o foobar
$ su -
# chown foobar.users /tmp/foobar
# chmod 4755 /tmp/foobar
# exit
$ ./foobar
If I run "./foobar" as other normal user(not "foobar" itself), it's gonna be error:
/tmp/script_of_foobar.sh: line 2: file_of_foobar: Permission denied
I am totally confused. Why the second scenario not working?
Best regards.
The setuid call in foobar.c will only succeed if you are root, or your effective UID is 1001.
So. If you're not root, setuid(1001) will fail, and you won't have the required rights to overwrite the file owned by "foobar".
From the output it looks like your non-root user is able to execute script_of_foobar.sh, but unable to write to /tmp/file_of_foobar. Are the permissions on /tmp possibly off? I believe it should be set to 1777.

Resources