I'm trying to write a program that will quickly shut down a laptop without prompting for a password or confirmation. The laptop is running Linux, specifically Manjaro.
To that end, I'm trying to make a setuid
executable called downnow
that executes shutdown
with fixed arguments (and also spawns a shell). I'm only using system
here to keep the program short, it's a terrible idea from a security standpoint.
// downnow.c
#include <stdlib.h>
int main() {
system("shutdown --no-wall --halt now");
return 0;
}
then I compiled downnow
, moved it to /bin
, changed its owner and gave it setuid and setgid permissions:
$ sudo chown root /bin/downnow
$ sudo chgrp root /bin/downnow
$ sudo chmod u+s /bin/downnow
$ sudo chmod g+s /bin/downnow
However, when I attempt to execute downnow
as an unprivileged user, it can't communicate with systemd.
$ downnow
Failed to halt system via logind: Interactive authentication required.
Failed to talk to init daemon.
I get the same message before and after ch{own,grp,mod}
ing.
stat
reports the same permissions on /bin/downnow
and /usr/bin/sudo
.
$ stat /bin/downnow
File: /bin/downnow
Size: XXXX Blocks: XX IO Block: XXXX regular file
Device: XXXXX/XXXXX Inode: XXXXXX Links: 1
Access: (6755/-rwsr-sr-x) Uid: ( 0/ root) Gid: ( 0/ root)
$ stat /usr/bin/sudo
File: /usr/bin/sudo
Size: XXXXXX Blocks: XXX IO Block: XXXX regular file
Device: XXXXX/XXXXX Inode: XXXXXXX Links: 1
Access: (4755/-rwsr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Why might downnow
fail to elevate its privileges when sudo
works perfectly?