suid executable not elevating permissions but `sudo` does elevate
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
add a comment |
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
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
add a comment |
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
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
setuid
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
add a comment |
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
add a comment |
2 Answers
2
active
oldest
votes
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.
The part that everyone is missing is thatInteractive 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 pullInteractive 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 necessarysetuid
call, and does not with thesetuid
call and appropriate ownership andu+s
bit set, as a trivial test on, say, Centos 7 will show.
– thrig
Jan 11 at 14:57
add a comment |
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;
}
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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
The part that everyone is missing is thatInteractive 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 pullInteractive 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 necessarysetuid
call, and does not with thesetuid
call and appropriate ownership andu+s
bit set, as a trivial test on, say, Centos 7 will show.
– thrig
Jan 11 at 14:57
add a comment |
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.
The part that everyone is missing is thatInteractive 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 pullInteractive 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 necessarysetuid
call, and does not with thesetuid
call and appropriate ownership andu+s
bit set, as a trivial test on, say, Centos 7 will show.
– thrig
Jan 11 at 14:57
add a comment |
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.
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.
answered Jan 10 at 1:41
thrigthrig
25k23157
25k23157
The part that everyone is missing is thatInteractive 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 pullInteractive 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 necessarysetuid
call, and does not with thesetuid
call and appropriate ownership andu+s
bit set, as a trivial test on, say, Centos 7 will show.
– thrig
Jan 11 at 14:57
add a comment |
The part that everyone is missing is thatInteractive 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 pullInteractive 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 necessarysetuid
call, and does not with thesetuid
call and appropriate ownership andu+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
add a comment |
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;
}
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
add a comment |
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;
}
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
add a comment |
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;
}
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;
}
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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