suid executable not elevating permissions but `sudo` does elevate












2















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?










share|improve this question

























  • Another approach is not writing any set-UID program at all, and setting up a PolicyKit rule. Most people want to disable the ability to shutdown. Enabling it is an exercise in the converse. unix.stackexchange.com/questions/263884 unix.stackexchange.com/questions/491038

    – JdeBP
    Jan 10 at 11:37
















2















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?










share|improve this question

























  • Another approach is not writing any set-UID program at all, and setting up a PolicyKit rule. Most people want to disable the ability to shutdown. Enabling it is an exercise in the converse. unix.stackexchange.com/questions/263884 unix.stackexchange.com/questions/491038

    – JdeBP
    Jan 10 at 11:37














2












2








2








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?










share|improve this question
















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?







setuid






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 4 hours ago







Gregory Nisbet

















asked Jan 10 at 0:48









Gregory NisbetGregory Nisbet

1,4341020




1,4341020













  • Another approach is not writing any set-UID program at all, and setting up a PolicyKit rule. Most people want to disable the ability to shutdown. Enabling it is an exercise in the converse. unix.stackexchange.com/questions/263884 unix.stackexchange.com/questions/491038

    – JdeBP
    Jan 10 at 11:37



















  • Another approach is not writing any set-UID program at all, and setting up a PolicyKit rule. Most people want to disable the ability to shutdown. Enabling it is an exercise in the converse. unix.stackexchange.com/questions/263884 unix.stackexchange.com/questions/491038

    – JdeBP
    Jan 10 at 11:37

















Another approach is not writing any set-UID program at all, and setting up a PolicyKit rule. Most people want to disable the ability to shutdown. Enabling it is an exercise in the converse. unix.stackexchange.com/questions/263884 unix.stackexchange.com/questions/491038

– JdeBP
Jan 10 at 11:37





Another approach is not writing any set-UID program at all, and setting up a PolicyKit rule. Most people want to disable the ability to shutdown. Enabling it is an exercise in the converse. unix.stackexchange.com/questions/263884 unix.stackexchange.com/questions/491038

– JdeBP
Jan 10 at 11:37










2 Answers
2






active

oldest

votes


















1














Probably due to a lack of a setuid(2) call. Here's a before and after around such a call:



#include <err.h>
#include <stdio.h>
#include <unistd.h>

#define GETUIDS(p) (p[0]=getuid(),p[1]=geteuid())

int main(void)
{
uid_t ids[2];
GETUIDS(ids);
fprintf(stderr, "real %lu effective %lun", (unsigned long) ids[0],
(unsigned long) ids[1]);
if (setuid(0) == -1)
err(1, "setuid failed");
GETUIDS(ids);
fprintf(stderr, "real %lu effective %lun", (unsigned long) ids[0],
(unsigned long) ids[1]);
return 0;
}


Also your wrapper is not really safe; hopefully it will not escape to multi-user systems. It would be likely much safer to avoid the needless shell call (unless you like shellshock type vulnerabilities or the strange handling of duplicate environment variables by, say, bash...) and instead use an exec(3) call to replace your process with shutdown directly:



#include <err.h>
#include <unistd.h>

int main()
{
if (setuid(0) == -1)
err(1, "setuid failed");
//execl("/usr/bin/echo", "echo", "--no-wall", "--halt", "now",
execl("/usr/sbin/shutdown", "shutdown", "--no-wall", "--halt", "now",
(char *) 0);
err(1, "exec failed");
return 1;
}


A few accidental shutdowns later...



centos7# make badcode
cc badcode.c -o badcode
centos7# mv badcode /badcode
centos7# chmod u+s /badcode
centos7# su - jhqdoe
Last login: Thu Jan 10 01:39:03 UTC 2019 on pts/0
[jhqdoe@centos7 ~]$ /badcode
Connection to 192.168.99.2 closed by remote host.
Connection to 192.168.99.2 closed.





share|improve this answer
























  • The part that everyone is missing is that Interactive authentication required. results from the PolicyKit rules processing, which does not happen in-process and which tests the effective UID not the real UID.

    – JdeBP
    Jan 10 at 12:18











  • @JdeBP huh? maybe post how you think policykit is involved in an answer? where did you pull Interactive authentication required from?

    – thrig
    Jan 10 at 14:40











  • From the question.

    – JdeBP
    Jan 11 at 9:22











  • @JdeBP yes, and? PolicyKit intrudes without the necessary setuid call, and does not with the setuid call and appropriate ownership and u+s bit set, as a trivial test on, say, Centos 7 will show.

    – thrig
    Jan 11 at 14:57



















2














Setting the permission bit only allows your application to use the setuid call and doesn't, by itself, change your permissions. To do that, you need to set the uid with setuid(uid_t uid). See the man page for details: https://linux.die.net/man/2/setuid



You can use geteuid() to get the current effective uid (i.e. the owner of the file with the setuid permission). See man page: https://linux.die.net/man/2/geteuid



Example:



// downnow.c
#include <stdlib.h>
#include <unistd.h>

int main() {
setuid(geteuid());
system("shutdown --no-wall --halt now");
return 0;
}





share|improve this answer
























  • That explanation will probably just confuse people. The set-ID permissions very much do change one's credentials. Indeed, you are copying those very changed effective credentials onto the real ones.

    – JdeBP
    Jan 10 at 11:47











Your Answer








StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f493583%2fsuid-executable-not-elevating-permissions-but-sudo-does-elevate%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














Probably due to a lack of a setuid(2) call. Here's a before and after around such a call:



#include <err.h>
#include <stdio.h>
#include <unistd.h>

#define GETUIDS(p) (p[0]=getuid(),p[1]=geteuid())

int main(void)
{
uid_t ids[2];
GETUIDS(ids);
fprintf(stderr, "real %lu effective %lun", (unsigned long) ids[0],
(unsigned long) ids[1]);
if (setuid(0) == -1)
err(1, "setuid failed");
GETUIDS(ids);
fprintf(stderr, "real %lu effective %lun", (unsigned long) ids[0],
(unsigned long) ids[1]);
return 0;
}


Also your wrapper is not really safe; hopefully it will not escape to multi-user systems. It would be likely much safer to avoid the needless shell call (unless you like shellshock type vulnerabilities or the strange handling of duplicate environment variables by, say, bash...) and instead use an exec(3) call to replace your process with shutdown directly:



#include <err.h>
#include <unistd.h>

int main()
{
if (setuid(0) == -1)
err(1, "setuid failed");
//execl("/usr/bin/echo", "echo", "--no-wall", "--halt", "now",
execl("/usr/sbin/shutdown", "shutdown", "--no-wall", "--halt", "now",
(char *) 0);
err(1, "exec failed");
return 1;
}


A few accidental shutdowns later...



centos7# make badcode
cc badcode.c -o badcode
centos7# mv badcode /badcode
centos7# chmod u+s /badcode
centos7# su - jhqdoe
Last login: Thu Jan 10 01:39:03 UTC 2019 on pts/0
[jhqdoe@centos7 ~]$ /badcode
Connection to 192.168.99.2 closed by remote host.
Connection to 192.168.99.2 closed.





share|improve this answer
























  • The part that everyone is missing is that Interactive authentication required. results from the PolicyKit rules processing, which does not happen in-process and which tests the effective UID not the real UID.

    – JdeBP
    Jan 10 at 12:18











  • @JdeBP huh? maybe post how you think policykit is involved in an answer? where did you pull Interactive authentication required from?

    – thrig
    Jan 10 at 14:40











  • From the question.

    – JdeBP
    Jan 11 at 9:22











  • @JdeBP yes, and? PolicyKit intrudes without the necessary setuid call, and does not with the setuid call and appropriate ownership and u+s bit set, as a trivial test on, say, Centos 7 will show.

    – thrig
    Jan 11 at 14:57
















1














Probably due to a lack of a setuid(2) call. Here's a before and after around such a call:



#include <err.h>
#include <stdio.h>
#include <unistd.h>

#define GETUIDS(p) (p[0]=getuid(),p[1]=geteuid())

int main(void)
{
uid_t ids[2];
GETUIDS(ids);
fprintf(stderr, "real %lu effective %lun", (unsigned long) ids[0],
(unsigned long) ids[1]);
if (setuid(0) == -1)
err(1, "setuid failed");
GETUIDS(ids);
fprintf(stderr, "real %lu effective %lun", (unsigned long) ids[0],
(unsigned long) ids[1]);
return 0;
}


Also your wrapper is not really safe; hopefully it will not escape to multi-user systems. It would be likely much safer to avoid the needless shell call (unless you like shellshock type vulnerabilities or the strange handling of duplicate environment variables by, say, bash...) and instead use an exec(3) call to replace your process with shutdown directly:



#include <err.h>
#include <unistd.h>

int main()
{
if (setuid(0) == -1)
err(1, "setuid failed");
//execl("/usr/bin/echo", "echo", "--no-wall", "--halt", "now",
execl("/usr/sbin/shutdown", "shutdown", "--no-wall", "--halt", "now",
(char *) 0);
err(1, "exec failed");
return 1;
}


A few accidental shutdowns later...



centos7# make badcode
cc badcode.c -o badcode
centos7# mv badcode /badcode
centos7# chmod u+s /badcode
centos7# su - jhqdoe
Last login: Thu Jan 10 01:39:03 UTC 2019 on pts/0
[jhqdoe@centos7 ~]$ /badcode
Connection to 192.168.99.2 closed by remote host.
Connection to 192.168.99.2 closed.





share|improve this answer
























  • The part that everyone is missing is that Interactive authentication required. results from the PolicyKit rules processing, which does not happen in-process and which tests the effective UID not the real UID.

    – JdeBP
    Jan 10 at 12:18











  • @JdeBP huh? maybe post how you think policykit is involved in an answer? where did you pull Interactive authentication required from?

    – thrig
    Jan 10 at 14:40











  • From the question.

    – JdeBP
    Jan 11 at 9:22











  • @JdeBP yes, and? PolicyKit intrudes without the necessary setuid call, and does not with the setuid call and appropriate ownership and u+s bit set, as a trivial test on, say, Centos 7 will show.

    – thrig
    Jan 11 at 14:57














1












1








1







Probably due to a lack of a setuid(2) call. Here's a before and after around such a call:



#include <err.h>
#include <stdio.h>
#include <unistd.h>

#define GETUIDS(p) (p[0]=getuid(),p[1]=geteuid())

int main(void)
{
uid_t ids[2];
GETUIDS(ids);
fprintf(stderr, "real %lu effective %lun", (unsigned long) ids[0],
(unsigned long) ids[1]);
if (setuid(0) == -1)
err(1, "setuid failed");
GETUIDS(ids);
fprintf(stderr, "real %lu effective %lun", (unsigned long) ids[0],
(unsigned long) ids[1]);
return 0;
}


Also your wrapper is not really safe; hopefully it will not escape to multi-user systems. It would be likely much safer to avoid the needless shell call (unless you like shellshock type vulnerabilities or the strange handling of duplicate environment variables by, say, bash...) and instead use an exec(3) call to replace your process with shutdown directly:



#include <err.h>
#include <unistd.h>

int main()
{
if (setuid(0) == -1)
err(1, "setuid failed");
//execl("/usr/bin/echo", "echo", "--no-wall", "--halt", "now",
execl("/usr/sbin/shutdown", "shutdown", "--no-wall", "--halt", "now",
(char *) 0);
err(1, "exec failed");
return 1;
}


A few accidental shutdowns later...



centos7# make badcode
cc badcode.c -o badcode
centos7# mv badcode /badcode
centos7# chmod u+s /badcode
centos7# su - jhqdoe
Last login: Thu Jan 10 01:39:03 UTC 2019 on pts/0
[jhqdoe@centos7 ~]$ /badcode
Connection to 192.168.99.2 closed by remote host.
Connection to 192.168.99.2 closed.





share|improve this answer













Probably due to a lack of a setuid(2) call. Here's a before and after around such a call:



#include <err.h>
#include <stdio.h>
#include <unistd.h>

#define GETUIDS(p) (p[0]=getuid(),p[1]=geteuid())

int main(void)
{
uid_t ids[2];
GETUIDS(ids);
fprintf(stderr, "real %lu effective %lun", (unsigned long) ids[0],
(unsigned long) ids[1]);
if (setuid(0) == -1)
err(1, "setuid failed");
GETUIDS(ids);
fprintf(stderr, "real %lu effective %lun", (unsigned long) ids[0],
(unsigned long) ids[1]);
return 0;
}


Also your wrapper is not really safe; hopefully it will not escape to multi-user systems. It would be likely much safer to avoid the needless shell call (unless you like shellshock type vulnerabilities or the strange handling of duplicate environment variables by, say, bash...) and instead use an exec(3) call to replace your process with shutdown directly:



#include <err.h>
#include <unistd.h>

int main()
{
if (setuid(0) == -1)
err(1, "setuid failed");
//execl("/usr/bin/echo", "echo", "--no-wall", "--halt", "now",
execl("/usr/sbin/shutdown", "shutdown", "--no-wall", "--halt", "now",
(char *) 0);
err(1, "exec failed");
return 1;
}


A few accidental shutdowns later...



centos7# make badcode
cc badcode.c -o badcode
centos7# mv badcode /badcode
centos7# chmod u+s /badcode
centos7# su - jhqdoe
Last login: Thu Jan 10 01:39:03 UTC 2019 on pts/0
[jhqdoe@centos7 ~]$ /badcode
Connection to 192.168.99.2 closed by remote host.
Connection to 192.168.99.2 closed.






share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 10 at 1:41









thrigthrig

25k23157




25k23157













  • The part that everyone is missing is that Interactive authentication required. results from the PolicyKit rules processing, which does not happen in-process and which tests the effective UID not the real UID.

    – JdeBP
    Jan 10 at 12:18











  • @JdeBP huh? maybe post how you think policykit is involved in an answer? where did you pull Interactive authentication required from?

    – thrig
    Jan 10 at 14:40











  • From the question.

    – JdeBP
    Jan 11 at 9:22











  • @JdeBP yes, and? PolicyKit intrudes without the necessary setuid call, and does not with the setuid call and appropriate ownership and u+s bit set, as a trivial test on, say, Centos 7 will show.

    – thrig
    Jan 11 at 14:57



















  • The part that everyone is missing is that Interactive authentication required. results from the PolicyKit rules processing, which does not happen in-process and which tests the effective UID not the real UID.

    – JdeBP
    Jan 10 at 12:18











  • @JdeBP huh? maybe post how you think policykit is involved in an answer? where did you pull Interactive authentication required from?

    – thrig
    Jan 10 at 14:40











  • From the question.

    – JdeBP
    Jan 11 at 9:22











  • @JdeBP yes, and? PolicyKit intrudes without the necessary setuid call, and does not with the setuid call and appropriate ownership and u+s bit set, as a trivial test on, say, Centos 7 will show.

    – thrig
    Jan 11 at 14:57

















The part that everyone is missing is that Interactive authentication required. results from the PolicyKit rules processing, which does not happen in-process and which tests the effective UID not the real UID.

– JdeBP
Jan 10 at 12:18





The part that everyone is missing is that Interactive authentication required. results from the PolicyKit rules processing, which does not happen in-process and which tests the effective UID not the real UID.

– JdeBP
Jan 10 at 12:18













@JdeBP huh? maybe post how you think policykit is involved in an answer? where did you pull Interactive authentication required from?

– thrig
Jan 10 at 14:40





@JdeBP huh? maybe post how you think policykit is involved in an answer? where did you pull Interactive authentication required from?

– thrig
Jan 10 at 14:40













From the question.

– JdeBP
Jan 11 at 9:22





From the question.

– JdeBP
Jan 11 at 9:22













@JdeBP yes, and? PolicyKit intrudes without the necessary setuid call, and does not with the setuid call and appropriate ownership and u+s bit set, as a trivial test on, say, Centos 7 will show.

– thrig
Jan 11 at 14:57





@JdeBP yes, and? PolicyKit intrudes without the necessary setuid call, and does not with the setuid call and appropriate ownership and u+s bit set, as a trivial test on, say, Centos 7 will show.

– thrig
Jan 11 at 14:57













2














Setting the permission bit only allows your application to use the setuid call and doesn't, by itself, change your permissions. To do that, you need to set the uid with setuid(uid_t uid). See the man page for details: https://linux.die.net/man/2/setuid



You can use geteuid() to get the current effective uid (i.e. the owner of the file with the setuid permission). See man page: https://linux.die.net/man/2/geteuid



Example:



// downnow.c
#include <stdlib.h>
#include <unistd.h>

int main() {
setuid(geteuid());
system("shutdown --no-wall --halt now");
return 0;
}





share|improve this answer
























  • That explanation will probably just confuse people. The set-ID permissions very much do change one's credentials. Indeed, you are copying those very changed effective credentials onto the real ones.

    – JdeBP
    Jan 10 at 11:47
















2














Setting the permission bit only allows your application to use the setuid call and doesn't, by itself, change your permissions. To do that, you need to set the uid with setuid(uid_t uid). See the man page for details: https://linux.die.net/man/2/setuid



You can use geteuid() to get the current effective uid (i.e. the owner of the file with the setuid permission). See man page: https://linux.die.net/man/2/geteuid



Example:



// downnow.c
#include <stdlib.h>
#include <unistd.h>

int main() {
setuid(geteuid());
system("shutdown --no-wall --halt now");
return 0;
}





share|improve this answer
























  • That explanation will probably just confuse people. The set-ID permissions very much do change one's credentials. Indeed, you are copying those very changed effective credentials onto the real ones.

    – JdeBP
    Jan 10 at 11:47














2












2








2







Setting the permission bit only allows your application to use the setuid call and doesn't, by itself, change your permissions. To do that, you need to set the uid with setuid(uid_t uid). See the man page for details: https://linux.die.net/man/2/setuid



You can use geteuid() to get the current effective uid (i.e. the owner of the file with the setuid permission). See man page: https://linux.die.net/man/2/geteuid



Example:



// downnow.c
#include <stdlib.h>
#include <unistd.h>

int main() {
setuid(geteuid());
system("shutdown --no-wall --halt now");
return 0;
}





share|improve this answer













Setting the permission bit only allows your application to use the setuid call and doesn't, by itself, change your permissions. To do that, you need to set the uid with setuid(uid_t uid). See the man page for details: https://linux.die.net/man/2/setuid



You can use geteuid() to get the current effective uid (i.e. the owner of the file with the setuid permission). See man page: https://linux.die.net/man/2/geteuid



Example:



// downnow.c
#include <stdlib.h>
#include <unistd.h>

int main() {
setuid(geteuid());
system("shutdown --no-wall --halt now");
return 0;
}






share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 10 at 1:45









Jonathan RouleauJonathan Rouleau

844




844













  • That explanation will probably just confuse people. The set-ID permissions very much do change one's credentials. Indeed, you are copying those very changed effective credentials onto the real ones.

    – JdeBP
    Jan 10 at 11:47



















  • That explanation will probably just confuse people. The set-ID permissions very much do change one's credentials. Indeed, you are copying those very changed effective credentials onto the real ones.

    – JdeBP
    Jan 10 at 11:47

















That explanation will probably just confuse people. The set-ID permissions very much do change one's credentials. Indeed, you are copying those very changed effective credentials onto the real ones.

– JdeBP
Jan 10 at 11:47





That explanation will probably just confuse people. The set-ID permissions very much do change one's credentials. Indeed, you are copying those very changed effective credentials onto the real ones.

– JdeBP
Jan 10 at 11:47


















draft saved

draft discarded




















































Thanks for contributing an answer to Unix & Linux Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f493583%2fsuid-executable-not-elevating-permissions-but-sudo-does-elevate%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Loup dans la culture

How to solve the problem of ntp “Unable to contact time server” from KDE?

ASUS Zenbook UX433/UX333 — Configure Touchpad-embedded numpad on Linux