forked from mirrors/tftp-hpa-google
tftpd: handle restricted user namespaces on Linux
If the tftpd process lacks the privilege to set its uid, gid, or groups, then assume it is already restricted in the way the administrator requested, if and only if EPERM is returned. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:
parent
15c4f369ee
commit
1dc6d55811
1 changed files with 25 additions and 8 deletions
|
@ -374,6 +374,7 @@ int main(int argc, char **argv)
|
||||||
int spec_umask = 0;
|
int spec_umask = 0;
|
||||||
int c;
|
int c;
|
||||||
int setrv;
|
int setrv;
|
||||||
|
int die;
|
||||||
int waittime = 900; /* Default time to wait for a connect */
|
int waittime = 900; /* Default time to wait for a connect */
|
||||||
const char *user = "nobody"; /* Default user */
|
const char *user = "nobody"; /* Default user */
|
||||||
char *p, *ep;
|
char *p, *ep;
|
||||||
|
@ -974,21 +975,30 @@ int main(int argc, char **argv)
|
||||||
exit(EX_IOERR);
|
exit(EX_IOERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up the supplementary group access list if possible */
|
/* Set up the supplementary group access list if possible
|
||||||
/* /etc/group still need to be accessible at this point */
|
/etc/group still need to be accessible at this point.
|
||||||
|
If we get EPERM, this is already a restricted process, e.g.
|
||||||
|
using user namespaces on Linux. */
|
||||||
|
setrv = -1;
|
||||||
|
die = 0;
|
||||||
#ifdef HAVE_INITGROUPS
|
#ifdef HAVE_INITGROUPS
|
||||||
setrv = initgroups(user, pw->pw_gid);
|
setrv = initgroups(user, pw->pw_gid);
|
||||||
if (setrv) {
|
if (setrv && errno != EPERM) {
|
||||||
syslog(LOG_ERR, "cannot set groups for user %s", user);
|
syslog(LOG_ERR, "cannot set groups for user %s", user);
|
||||||
exit(EX_OSERR);
|
die = EX_OSERR;
|
||||||
}
|
}
|
||||||
#else
|
#endif
|
||||||
#ifdef HAVE_SETGROUPS
|
#ifdef HAVE_SETGROUPS
|
||||||
if (setgroups(0, NULL)) {
|
if (setrv) {
|
||||||
|
setrv = setgroups(0, NULL);
|
||||||
|
if (setrv && errno != EPERM) {
|
||||||
syslog(LOG_ERR, "cannot clear group list");
|
syslog(LOG_ERR, "cannot clear group list");
|
||||||
|
die = EX_OSERR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
if (die)
|
||||||
|
exit(die);
|
||||||
|
|
||||||
/* Chroot and drop privileges */
|
/* Chroot and drop privileges */
|
||||||
if (secure) {
|
if (secure) {
|
||||||
|
@ -1000,11 +1010,15 @@ int main(int argc, char **argv)
|
||||||
chdir("/"); /* Cygwin chroot() bug workaround */
|
chdir("/"); /* Cygwin chroot() bug workaround */
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SETREGID
|
#ifdef HAVE_SETREGID
|
||||||
setrv = setregid(pw->pw_gid, pw->pw_gid);
|
setrv = setregid(pw->pw_gid, pw->pw_gid);
|
||||||
#else
|
#else
|
||||||
setrv = setegid(pw->pw_gid) || setgid(pw->pw_gid);
|
setrv = setegid(pw->pw_gid) || setgid(pw->pw_gid);
|
||||||
#endif
|
#endif
|
||||||
|
if (setrv && errno == EPERM) {
|
||||||
|
setrv = 0; /* Already restricted */
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SETREUID
|
#ifdef HAVE_SETREUID
|
||||||
setrv = setrv || setreuid(pw->pw_uid, pw->pw_uid);
|
setrv = setrv || setreuid(pw->pw_uid, pw->pw_uid);
|
||||||
|
@ -1013,6 +1027,9 @@ int main(int argc, char **argv)
|
||||||
setrv = setrv || setuid(pw->pw_uid) ||
|
setrv = setrv || setuid(pw->pw_uid) ||
|
||||||
(geteuid() != pw->pw_uid && seteuid(pw->pw_uid));
|
(geteuid() != pw->pw_uid && seteuid(pw->pw_uid));
|
||||||
#endif
|
#endif
|
||||||
|
if (setrv && errno == EPERM) {
|
||||||
|
setrv = 0; /* Already restricted */
|
||||||
|
}
|
||||||
|
|
||||||
if (setrv) {
|
if (setrv) {
|
||||||
syslog(LOG_ERR, "cannot drop privileges: %m");
|
syslog(LOG_ERR, "cannot drop privileges: %m");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue