Implement a new magic string for magic symlinks, @ruid, which exapnds to the

real user id of the process and use this magic string for per-user tmp.
This should fix PR/35687

Kernel parts reviewed by wrstuden@
This commit is contained in:
mjf 2007-12-04 22:09:01 +00:00
parent fe819e7531
commit d4a648c345
5 changed files with 91 additions and 24 deletions

View File

@ -1,6 +1,6 @@
#!/bin/sh
#
# $NetBSD: cleartmp,v 1.9 2007/02/15 08:47:38 xtraeme Exp $
# $NetBSD: cleartmp,v 1.10 2007/12/04 22:09:01 mjf Exp $
#
# PROVIDE: cleartmp
@ -28,7 +28,7 @@ cleartmp_start()
tmp_dir="/tmp"
# Check if /tmp was created by the perusertmp rc.d
# script and recreate it if necessary.
if [ "$(/usr/bin/readlink /tmp)" = ${per_user_tmp_dir}/@uid ]; then
if [ "$(/usr/bin/readlink /tmp)" = ${per_user_tmp_dir}/@ruid ]; then
/bin/rm -rf ${tmp_dir}
/bin/mkdir ${tmp_dir}
/usr/sbin/chown root:wheel ${tmp_dir}

View File

@ -1,6 +1,6 @@
#!/bin/sh
#
# $NetBSD: perusertmp,v 1.6 2007/02/15 13:27:35 tron Exp $
# $NetBSD: perusertmp,v 1.7 2007/12/04 22:09:01 mjf Exp $
#
# PROVIDE: perusertmp
@ -40,9 +40,9 @@ perusertmp_start()
/bin/chmod 0555 ${per_user_tmp_dir}
# Create magic link for /tmp.
if [ "$(/usr/bin/readlink /tmp)" != ${per_user_tmp_dir}/@uid ]; then
if [ "$(/usr/bin/readlink /tmp)" != ${per_user_tmp_dir}/@ruid ]; then
/bin/rm -rf /tmp
/bin/ln -s ${per_user_tmp_dir}/@uid /tmp
/bin/ln -s ${per_user_tmp_dir}/@ruid /tmp
fi
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: login_cap.c,v 1.28 2007/10/06 21:51:22 christos Exp $ */
/* $NetBSD: login_cap.c,v 1.29 2007/12/04 22:09:02 mjf Exp $ */
/*-
* Copyright (c) 1995,1997 Berkeley Software Design, Inc. All rights reserved.
@ -36,7 +36,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: login_cap.c,v 1.28 2007/10/06 21:51:22 christos Exp $");
__RCSID("$NetBSD: login_cap.c,v 1.29 2007/12/04 22:09:02 mjf Exp $");
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
@ -559,9 +559,11 @@ int
setusercontext(login_cap_t *lc, struct passwd *pwd, uid_t uid, u_int flags)
{
char per_user_tmp[MAXPATHLEN + 1];
const char *component_name;
login_cap_t *flc;
quad_t p;
int i;
ssize_t len;
flc = NULL;
@ -617,27 +619,73 @@ setusercontext(login_cap_t *lc, struct passwd *pwd, uid_t uid, u_int flags)
}
/* Create per-user temporary directories if needed. */
if (readlink("/tmp", per_user_tmp, sizeof(per_user_tmp)) != -1) {
static const char atuid[] = "/@uid";
if ((len = readlink("/tmp", per_user_tmp,
sizeof(per_user_tmp) - 6)) != -1) {
static const char atuid[] = "/@ruid";
char *lp;
/* readlink does not nul-terminate the string */
per_user_tmp[len] = '\0';
/* Check if it's magic symlink. */
lp = strstr(per_user_tmp, atuid);
if (lp != NULL && *(lp + (sizeof(atuid) - 1)) == '\0') {
lp++;
if ((sizeof(per_user_tmp) - (lp - per_user_tmp)) < 64) {
if (snprintf(lp, 11, "/%u", pwd->pw_uid) > 10) {
syslog(LOG_ERR, "real temporary path too long");
login_close(flc);
return (-1);
}
(void)sprintf(lp, "/%u", pwd->pw_uid); /* safe */
if (mkdir(per_user_tmp, S_IRWXU) != -1) {
(void)chown(per_user_tmp, pwd->pw_uid,
pwd->pw_gid);
if (chown(per_user_tmp, pwd->pw_uid,
pwd->pw_gid)) {
component_name = "chown";
goto out;
}
/*
* Must set sticky bit for tmp directory, some
* programs rely on this.
*/
if(chmod(per_user_tmp, S_IRWXU | S_ISVTX)) {
component_name = "chmod";
goto out;
}
} else {
syslog(LOG_ERR, "can't create `%s' directory",
per_user_tmp);
if (errno != EEXIST) {
component_name = "mkdir";
goto out;
} else {
/*
* We must ensure that we own the
* directory and that is has the correct
* permissions, otherwise a DOS attack
* is possible.
*/
struct stat sb;
if (stat(per_user_tmp, &sb) == -1) {
component_name = "stat";
goto out;
}
if (sb.st_uid != pwd->pw_uid) {
if (chown(per_user_tmp,
pwd->pw_uid, pwd->pw_gid)) {
component_name = "chown";
goto out;
}
}
if (sb.st_mode != (S_IRWXU | S_ISVTX)) {
if (chmod(per_user_tmp,
S_IRWXU | S_ISVTX)) {
component_name = "chmod";
goto out;
}
}
}
}
}
}
@ -666,6 +714,17 @@ setusercontext(login_cap_t *lc, struct passwd *pwd, uid_t uid, u_int flags)
login_close(flc);
return (0);
out:
if (component_name != NULL) {
syslog(LOG_ERR, "%s %s: %m", component_name, per_user_tmp);
login_close(flc);
return (-1);
} else {
syslog(LOG_ERR, "%s: %m", per_user_tmp);
login_close(flc);
return (-1);
}
}
void

View File

@ -1,4 +1,4 @@
.\" $NetBSD: symlink.7,v 1.12 2007/02/07 06:41:50 wiz Exp $
.\" $NetBSD: symlink.7,v 1.13 2007/12/04 22:09:02 mjf Exp $
.\"
.\" Copyright (c) 1992, 1993, 1994
.\" The Regents of the University of California. All rights reserved.
@ -432,11 +432,13 @@ or
.Fl P
options.
.Sh MAGIC SYMLINKS
Symlinks in file systems with the
.Li MNT_MAGICLINKS
flag set have
Magic symlinks can be enabled by setting
.Dq vfs.generic.magiclinks
with
.Xr sysctl 8 .
When magic symlinks are enabled
.Dq magic
patterns in symlinks expanded.
patterns in symlinks are expanded.
Those patterns begin with
.Dq @
.Pq an at-sign ,
@ -518,6 +520,8 @@ This will always be
on
.Nx
systems.
.It @ruid
Exapnds to the real user-id of the process.
.It @uid
Expands to the effective user-id of the process.
.El

View File

@ -1,4 +1,4 @@
/* $NetBSD: vfs_lookup.c,v 1.100 2007/11/26 19:02:07 pooka Exp $ */
/* $NetBSD: vfs_lookup.c,v 1.101 2007/12/04 22:09:02 mjf Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.100 2007/11/26 19:02:07 pooka Exp $");
__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.101 2007/12/04 22:09:02 mjf Exp $");
#include "opt_systrace.h"
#include "opt_magiclinks.h"
@ -120,6 +120,8 @@ symlink_magic(struct proc *p, char *cp, int *len)
char *tmp;
int change, i, newlen;
int termchar = '/';
char uidtmp[11]; /* XXX elad */
tmp = PNBUF_GET();
for (change = i = newlen = 0; i < *len; ) {
@ -165,11 +167,13 @@ symlink_magic(struct proc *p, char *cp, int *len)
SUBSTITUTE("ostype", ostype,
strlen(ostype));
} else if (MATCH("uid")) {
char uidtmp[11]; /* XXX elad */
(void)snprintf(uidtmp, sizeof(uidtmp), "%u",
kauth_cred_geteuid(kauth_cred_get()));
SUBSTITUTE("uid", uidtmp, strlen(uidtmp));
} else if (MATCH("ruid")) {
(void)snprintf(uidtmp, sizeof(uidtmp), "%u",
kauth_cred_getuid(kauth_cred_get()));
SUBSTITUTE("ruid", uidtmp, strlen(uidtmp));
} else {
tmp[newlen++] = '@';
if (termchar == VC)