-----BEGIN PGP SIGNED MESSAGE----- Hi all, Prompted by Mark''s discussion of the transname patch I''ve put together an experimental patch to the Linux nfsd that supports something I''ve named CDFs for lack of a more appropriate name. They''re not real CDFs, and in particular, they won''t let you manage stuff like shared /etc directories for diskless clients (it breaks /etc/mtab handling, for instance). I''m not particularly proud of it since I consider CDFs a kludge by all means, but as it was feasible with less than 10 minutes of hacking, I thought I''d put this suggestion forward. As far as I can see, it suffers from none of the problems Mark found with the transname patch, including the symlink check some security-aware programs perform (since they usually check whether the /tmp/foo file is a symlink, not /tmp itself). It works basically by recognizing and replacing `magic'' path components at lookup time. To provide per-user /tmp directories transparently, you would have to do something like this: # Create per-user temp directories mkdir -pm 755 /.tmp/users /.tmp/switch for uid in 0 1 2 3 4 5 6 .. 500 501 ...; do mkdir -m 755 /.tmp/users/$uid chown $uid.users /.tmp/users/$uid ln -s /.tmp/users/$uid /.tmp/switch/$uid done mkdir -pm 1777 /.tmp/users/default; ln -s /.tmp/users/default /.tmp/switch/default # Prepare NFS-mounted /.tmp/switch directory mkdir -pm 755 /.tmp/nfs mount localhost:/.tmp/switch /.tmp/nfs -o noac # Replace old /tmp directory mv /tmp /tmp.old ln -s /.tmp/nfs/cdf:uid /tmp That looks somewhat convoluted, so let me explain how it works: When a process tries to look up /tmp, it will read the symlink pointing to /.tmp/nfs/cdf:uid. Looking up the symlink, it will encounter the NFS mount point (/.tmp/nfs), and ask the NFS server to look up "cdf:uid". Nfsd will recognize the special name and replace it with the requesting process'' numeric uid (let''s say 500) before looking it up. It will now encounter yet another symlink, this time pointing to /.tmp/users/500 which is the user''s private temporary directory. Once the kernel has obtained this path, subsequent lookups will not have to go through the server any more. The /.tmp/switch/default symlink is somewhat special; this is the fallback name used when nfsd is not able to look up the uid-specific directory. In the above setting, it provides the usual /tmp semantics for uids for which you haven''t created a specific /.tmp/users directory. If you choose to omit the default entry, a lookup of cdf:uid for such a uid will fail, which may or may not be what you want. Note the noac option when mounting /.tmp/switch over NFS. This is absolutely crucial, because otherwise the kernel would cache the result of looking up cdf:uid, leading to random behavior. Also take care of the export options for /.tmp/switch: using ro is not a problem but doesn''t add much in terms of security. It''s up to you whether you enable root squashing or not; enabling it may have unexpected side effects... The above setup should also work nicely with setuid applications that `forget'' to yield their privileges before creating or manipulating a file in /tmp. Since the kernel uses the fsuid of the process (which is in effect its euid most of the time) when constructing the RPC credentials for the NFS call, it will automatically be redirected to its uid-specific /.tmp/users directory that cannot be booby-trapped by an attacker. Depending on your boot setup, you may also have to modify your rc files because nfsd my not yet be running when the first programs try to use /tmp. In this case, make /tmp a symlink to some other location first, and flip it to /.tmp/nfs/cdf:uid after nfsd is running. Oh, I almost forgot to mention this: to enable CDF support in nfsd, you must edit the Makefile and add -DSUPPORT_CDF to the NFSD_DEFS variable. The complete source for nfsd-2.2beta23 can be found on ftp://ftp.mathematik.th-darmstadt.de/pub/linux/okir . Criticism and suggestions welcome, but please allow for some days before I find the time to reply. Happy hacking Olaf <A HREF="; mailx -s ''youve been hacked'' $LOGNAME">Test your mailer!</A> - ------------------------------------------------------------------ diff -ur nfs-server-2.2beta23/ChangeLog nfs-server-2.2beta23/ChangeLog - --- nfs-server-2.2beta23/ChangeLog Wed Sep 25 01:22:27 1996 +++ nfs-server-2.2beta23/ChangeLog Fri Nov 15 11:50:52 1996 @@ -1,3 +1,7 @@ +Fri Nov 15 11:50:28 1996 Olaf Kirch <okir@monad.swb.de> + + * Added experimental CDF support. See README.CDF for details. + Wed Sep 25 01:19:25 1996 Olaf Kirch <okir@monad.swb.de> * Fixed a very old bug in the file handle cache. When many diff -ur nfs-server-2.2beta23/Makefile.in nfs-server-2.2beta23/Makefile.in - --- nfs-server-2.2beta23/Makefile.in Fri Sep 20 17:35:50 1996 +++ nfs-server-2.2beta23/Makefile.in Fri Nov 15 10:43:06 1996 @@ -42,8 +42,13 @@ # DOSHACKS # This is a hack that lets DOS boxes mount NFS volumes with all_squash # enabled and actually write to them, even though their uid/gid does - -# not match the non_uid/anon_gid. Ugly, and not officially supported. +# not match the anon_uid/anon_gid. Ugly, and not officially supported. # (Don''t you call me a hypocrite:) +# SUPPORT_CDF +# Experimental support for context-dependent files on LOOKUP. +# Currently supported names are cdf:uid and cdf:hostaddr. When a +# CDF component cannot be looked up, it will be replaced with +# the catch-all name "default". # DEBUG # General debugging enable flag #NFSD_DEFS = -DCALL_PROFILING diff -ur nfs-server-2.2beta23/nfsd.c nfs-server-2.2beta23/nfsd.c - --- nfs-server-2.2beta23/nfsd.c Wed Sep 25 00:37:42 1996 +++ nfs-server-2.2beta23/nfsd.c Fri Nov 15 10:45:37 1996 @@ -85,6 +85,9 @@ static _PRO (void usage, (FILE *, int) ); static _PRO (void terminate, (void) ); static _PRO (RETSIGTYPE sigterm, (int sig) ); +#ifdef SUPPORT_CDF +static _PRO (char *cdf_translate, (char *tag) ); +#endif #ifdef CALL_PROFILING @@ -279,6 +282,24 @@ if (auth_fh(rqstp, &(argp->dir), &status, CHK_READ) == NULL) return status; +#ifdef SUPPORT_CDF + /* This is just some experimental support for context-dependent + * files in order to cope with mindless use of /tmp. + */ + if (!strncmp(argp->name, "cdf:", 4)) { + char *oldname = argp->name; + + if ((argp->name = cdf_translate(argp->name + 4)) != NULL) { + status = fh_compose(argp, &(dp->file), &sbp, -1, -1); + } else + status = NFSERR_NOENT; + if (status == NFSERR_NOENT) { + argp->name = "default"; + status = fh_compose(argp, &(dp->file), &sbp, -1, -1); + } + argp->name = oldname; + } else +#endif status = fh_compose(argp, &(dp->file), &sbp, -1, -1); if (status != NFS_OK) return status; @@ -294,6 +315,22 @@ return (status); } +#ifdef SUPPORT_CDF +static char * +cdf_translate(char *tag) +{ + static char buffer[512]; + + if (tag[0] == ''u'' && !strcmp(tag, "uid")) + sprintf(buffer, "%d", auth_uid); + else if (tag[0] == ''h'' && !strcmp(tag, "hostaddr")) + sprintf(buffer, "%s", inet_ntoa(nfsclient->clnt_addr)); + else + return NULL; + return buffer; +} +#endif + int nfsd_nfsproc_readlink_2(argp, rqstp) nfs_fh *argp; struct svc_req *rqstp; -----BEGIN PGP SIGNATURE----- Version: 2.6.2i iQCVAwUBMpIqrOFnVHXv40etAQG6QgP/YduasTIkcOgs/dM8CvHK9gr6P5oPqOq6 5EextZDlVKwK7Ajh6hq/wia4WjqZAkbRIbuf69Wv/wuQDkVxuDfdLuQaabwEcCi1 bOVJxS+efvKfgDqxj5YneQw4GEPDb7nDjAaQMH5h4sng83IKBDTOrYUiNSp6Ws2z DrPK5MQOXY0=X61A -----END PGP SIGNATURE----- From mail@mail.redhat.com Tue Nov 19 20:57:12 1996