Subject: per-user /tmp
To: None <tech-security@netbsd.org>
From: Elad Efrat <elad@NetBSD.org>
List: tech-security
Date: 02/03/2007 19:23:26
This is a multi-part message in MIME format.
--------------000602050607070207080607
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
hi,
attached are some diffs & instructions on how we can add support for
per-user /tmp directories. the motivation is of course to avoid /tmp
races.
1. enable magic links:
# sysctl -w vfs.generic.magiclinks=1
2. decide on a directory that should be the per-user /tmp base, and
set the symlink:
# rmdir /tmp
# mkdir /rtmp
# ln -s /rtmp/@uid /tmp
note that /rtmp in this case should be the mount-point if /tmp is
a tmpfs or something.
3. each user using /tmp should have a directory under /rtmp named after
the uid, set 0700. for example:
# mkdir /rtmp/1000 -m 0700
# chown user:user /rtmp/1000
the attached login.diff will help doing that automatically for users
when they login. it will read a string variable 'per-user-tmp' from
login.conf during login, creating the directory (if it's not already
there).
for example:
# from login.conf:
default:\
:per-user-tmp=/rtmp:
will set /rtmp as the per-user /tmp base.
4. if the above goes in, it will of course be disabled by default.
thoughts?
-e.
--------------000602050607070207080607
Content-Type: text/plain;
name="login.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="login.diff"
Index: login.c
===================================================================
RCS file: /usr/cvs/src/usr.bin/login/login.c,v
retrieving revision 1.94
diff -u -p -r1.94 login.c
--- login.c 17 Jan 2007 00:21:43 -0000 1.94
+++ login.c 2 Feb 2007 06:22:14 -0000
@@ -188,6 +188,7 @@ main(int argc, char *argv[])
#ifdef LOGIN_CAP
char *shell = NULL;
login_cap_t *lc = NULL;
+ char *per_user_tmp;
#endif
tbuf[0] = '\0';
@@ -596,6 +597,22 @@ main(int argc, char *argv[])
environ = envinit;
#ifdef LOGIN_CAP
+ /* Create per-user temporary directories if needed. */
+ per_user_tmp = login_getcapstr(lc, "per-user-tmp", NULL, NULL);
+ if (per_user_tmp != NULL) {
+ char *tmp_dir;
+
+ /* Ignore errors here. */
+ if (asprintf(&tmp_dir, "%s/%u", per_user_tmp,
+ pwd->pw_uid) != -1) {
+ (void)mkdir(tmp_dir, S_IRWXU);
+ (void)chown(tmp_dir, pwd->pw_uid, pwd->pw_gid);
+ free(tmp_dir);
+ }
+ }
+#endif /* LOGIN_CAP */
+
+#ifdef LOGIN_CAP
if (nested == NULL && setusercontext(lc, pwd, pwd->pw_uid,
LOGIN_SETLOGIN) != 0) {
syslog(LOG_ERR, "setusercontext failed");
Index: login_pam.c
===================================================================
RCS file: /usr/cvs/src/usr.bin/login/login_pam.c,v
retrieving revision 1.17
diff -u -p -r1.17 login_pam.c
--- login_pam.c 17 Apr 2006 16:29:44 -0000 1.17
+++ login_pam.c 2 Feb 2007 06:20:21 -0000
@@ -144,6 +144,7 @@ main(int argc, char *argv[])
int status;
char *saved_term;
char **pamenv;
+ char *per_user_tmp;
tbuf[0] = '\0';
pwprompt = NULL;
@@ -643,6 +644,20 @@ skip_auth:
free(pamenv);
}
+ /* Create per-user temporary directories if needed. */
+ per_user_tmp = login_getcapstr(lc, "per-user-tmp", NULL, NULL);
+ if (per_user_tmp != NULL) {
+ char *tmp_dir;
+
+ /* Ignore errors here. */
+ if (asprintf(&tmp_dir, "%s/%u", per_user_tmp,
+ pwd->pw_uid) != -1) {
+ (void)mkdir(tmp_dir, S_IRWXU);
+ (void)chown(tmp_dir, pwd->pw_uid, pwd->pw_gid);
+ free(tmp_dir);
+ }
+ }
+
/* This drops root privs */
if (setusercontext(lc, pwd, pwd->pw_uid,
(LOGIN_SETALL & ~LOGIN_SETLOGIN)) != 0) {
--------------000602050607070207080607--