aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew G. Morgan <morgan@kernel.org>2022-04-30 16:04:47 -0700
committerAndrew G. Morgan <morgan@kernel.org>2022-04-30 16:04:47 -0700
commiteb0f1df722d5e760137a0dd85fee8e78c95ee68f (patch)
tree1ddbb73ecd65ccf72d2e0efeb1aa72a0061d4cb9
parent9a9579181897a62dc107b121f139a319d7e297fa (diff)
downloadlibcap-eb0f1df722d5e760137a0dd85fee8e78c95ee68f.tar.gz
Prevent 'capsh --user=xxx --' from generating a bash error.
This change adds support to capsh for the --noenv argument, which will restore pre-libcap-2.65 behavior to capsh. The change we're making here, however, is that capsh will now set the USER and HOME environment variables when the command line contains --user=xxx. The issue this addresses is described here: https://bugzilla.kernel.org/show_bug.cgi?id=215926 This has been annoying me for long enough, and I want to clean up the article: https://sites.google.com/site/fullycapable/inheriting-privilege to not pepper "--norc" in distracting places. Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
-rw-r--r--doc/capsh.16
-rw-r--r--progs/capsh.c19
2 files changed, 24 insertions, 1 deletions
diff --git a/doc/capsh.1 b/doc/capsh.1
index aafe3fb..4f3aaae 100644
--- a/doc/capsh.1
+++ b/doc/capsh.1
@@ -329,6 +329,12 @@ Removes the specified ambient capability from the running process.
.B \-\-noamb
Drops all ambient capabilities from the running process.
.TP
+.B \-\-noenv
+Suppresses overriding of the HOME and USER environment variables when
+a subsequent
+.B \-\-user
+argument is processed.
+.TP
.B \-\-quiet
This argument is ignored unless it is the first one. If present, it
suppresses the capsh runtime check to confirm the running libcap is
diff --git a/progs/capsh.c b/progs/capsh.c
index 4f568c3..f753291 100644
--- a/progs/capsh.c
+++ b/progs/capsh.c
@@ -509,7 +509,7 @@ int main(int argc, char *argv[], char *envp[])
{
pid_t child = 0;
unsigned i;
- int strict = 0, quiet_start = 0;
+ int strict = 0, quiet_start = 0, dont_set_env = 0;
const char *shell = SHELL;
for (i=1; i<argc; ++i) {
@@ -558,6 +558,8 @@ int main(int argc, char *argv[], char *envp[])
perror("failed to reset ambient set");
exit(1);
}
+ } else if (!strcmp("--noenv", argv[i])) {
+ dont_set_env = 1;
} else if (!strncmp("--inh=", argv[i], 6)) {
cap_t all, raised_for_setpcap;
char *text;
@@ -912,6 +914,20 @@ int main(int argc, char *argv[], char *envp[])
pwd->pw_uid, user, strerror(errno));
exit(1);
}
+ if (!dont_set_env) {
+ /*
+ * not setting this confuses bash at start up, but use
+ * --noenv to preserve the HOME etc values instead.
+ */
+ if (setenv("HOME", pwd->pw_dir, 1) != 0) {
+ perror("unable to set HOME");
+ exit(1);
+ }
+ if (setenv("USER", user, 1) != 0) {
+ perror("unable to set USER");
+ exit(1);
+ }
+ }
} else if (!strncmp("--decode=", argv[i], 9)) {
unsigned long long value;
unsigned cap;
@@ -1170,6 +1186,7 @@ int main(int argc, char *argv[], char *envp[])
" --modes list libcap named modes\n"
" --no-new-privs set sticky process privilege limiter\n"
" --noamb reset (drop) all ambient capabilities\n"
+ " --noenv no fixup of env vars (for --user)\n"
" --print display capability relevant state\n"
" --quiet if first argument skip max cap check\n"
" --secbits=<n> write a new value for securebits\n"