Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 8 Nov 1997 20:36:20 -0800 (PST)
From:      Julian Elischer <julian@FreeBSD.ORG>
To:        hackers@FreeBSD.ORG
Subject:   How useful is this patch?
Message-ID:  <199711090436.UAA26951@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
In an application we have, several (many) naive PC and MAC users are using
SAMBA, FTP, and NETATALK, to access a filesystem. (under FreeBSD)

The problem is that there are cases where one unpriveliged user needs
to put files in the 'home directories' of other users. This is OK as long
as the owner of the directory can delete them.

For single files this is the case, however when the other user needs
to put a hierarchy of directories there, the poor owner of the original
directory can't because the directories are owned by someone else,
and they are not empty, so there is a catch 22, and they cannot be deleted.

These users, as I said before are simplistic, there are thousands of them,
and they (ALL OF THEM) don't like the answer "Oh that's the way UNIX works".

it gets more complicated when you start adding .AppleDouble directories
from netatalk, which may be created by an admin, using a MAC, but which are 
invisible to both the MAC and SAMBA users. They will be owned by the admin
and the user can't see why he can't delete the directry.

There are two answers.
1/ A CRAWLER that sets the ownerships of all user's directories contents
to the user. Simple, but not immediate, and I don't think it's the right answer.

2/ A HACK to UFS.

Here is the hack idea.
if a mount option is specified, then setting the SUID bit
on a directory specifies similar inheritance with UIDS as we 
presently have with GIDs. In other words, if the USER's home directory
is SUID, then when user B places a hierarchy of files into USER A's
directory, they become owned by user A. This corresponds exactly
with how naive PC users expect things to work.
"It's in my folder so it's mine"
The SUID bits are hereditary to child directories, and
a file 'given away' in this manner 
  1/ cannot be give n to root (would defeat quotas)
  2/ has the execute bits stripped off (and suid)

The advantage to this is that SAMBA and NETATALK, FTP and any other utilities
one may think of, suddenly all start exhibiting 'DOS-USER friendly'
behaviour, without needing to change and maintain those packages.
It can also be turned on and off
so that it would not be turned on in parts of the filesystem used by
'real' users.

THOUGHTS PLEASE!
(is it useful enough to add to the tree?)

here's the patch.
the first part is for making new directories, while the second part
is for making new files.

Index: ufs_vnops.c
===================================================================
RCS file: /cvs/freebsd/src/sys/ufs/ufs/ufs_vnops.c,v
retrieving revision 1.41.2.3
diff -c -r1.41.2.3 ufs_vnops.c
*** 1.41.2.3	1997/06/29 08:48:50
--- ufs_vnops.c	1997/11/09 03:58:50
***************
*** 1301,1308 ****
  	if (error)
  		goto out;
  	ip = VTOI(tvp);
- 	ip->i_uid = cnp->cn_cred->cr_uid;
  	ip->i_gid = dp->i_gid;
  #ifdef QUOTA
  	if ((error = getinoquota(ip)) ||
  	    (error = chkiq(ip, 1, cnp->cn_cred, 0))) {
--- 1301,1358 ----
  	if (error)
  		goto out;
  	ip = VTOI(tvp);
  	ip->i_gid = dp->i_gid;
+ #ifdef USE_SUIDDIR
+ 	{
+ #ifdef QUOTA
+ 		struct ucred ucred, *ucp;
+ 		ucp = cnp->cn_cred
+ #endif			I
+ 		/*
+ 		 * if we are hacking owners here, (only do this where told to)
+ 		 * and we are not giving it TOO root, (would subvert quotas)
+ 		 * then go ahead and give it to the other user.
+ 		 * The new directory also inherits the SUID bit. 
+ 		 * If user's UID an ddir UID are the same,
+ 		 * 'give it away' so that the SUID is still forced on.
+ 		 */
+ 		if ( (dvp->v_mount->mnt_flag & MNT_SUIDDIR)
+ 		&& (dp->i_mode & ISUID)
+ 		&& dp->i_uid) {
+ 			dmode |= ISUID;
+ 			ip->i_uid = dp->i_uid;
+ #ifdef QUOTA
+ 			if (pdir->i_uid != cnp->cn_cred->cr_uid) {
+ 				/*
+ 				 * make sure the correct user gets charged
+ 				 * for the space.
+ 				 * Make a dummy credential for the victim.
+ 				 * XXX This seems to never be accessed out of
+ 				 * our context so a stack variable is ok.
+ 				 */
+ 				ucred.cr_ref = 1
+ 				ucred.cr_uid = ip->i_uid;
+ 				ucred.cr_ngroups = 1
+ 				ucred.cr_groups[0] = dp->i_gid;
+ 				ucp = *ucred;
+ 			}
+ #endif			I
+ 		} else {
+ 			ip->i_uid = cnp->cn_cred->cr_uid;
+ 		}
+ #ifdef QUOTA
+ 		if ((error = getinoquota(ip)) ||
+ 	    	(error = chkiq(ip, 1, ucp, 0))) {
+ 			free(cnp->cn_pnbuf, M_NAMEI);
+ 			VOP_VFREE(tvp, ip->i_number, dmode);
+ 			vput(tvp);
+ 			vput(dvp);
+ 			return (error);
+ 		}
+ #endif
+ 	}
+ #else
+ 	ip->i_uid = cnp->cn_cred->cr_uid;
  #ifdef QUOTA
  	if ((error = getinoquota(ip)) ||
  	    (error = chkiq(ip, 1, cnp->cn_cred, 0))) {
***************
*** 1313,1318 ****
--- 1364,1370 ----
  		return (error);
  	}
  #endif
+ #endif
  	ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
  	ip->i_mode = dmode;
  	tvp->v_type = VDIR;	/* Rest init'd in getnewvnode(). */
***************
*** 2131,2136 ****
--- 2183,2238 ----
  	}
  	ip = VTOI(tvp);
  	ip->i_gid = pdir->i_gid;
+ #ifdef USE_SUIDDIR
+ 	{
+ #ifdef QUOTA
+ 		struct ucred ucred, *ucp;
+ 		ucp = cnp->cn_cred
+ #endif			I
+ 		/*
+ 		 * if we are
+ 		 * not the owner of the directory,
+ 		 * and we are hacking owners here, (only do this where told to)
+ 		 * and we are not giving it TOO root, (would subvert quotas)
+ 		 * then go ahead and give it to the other user.
+ 		 * Note that this drops off the execute bits for security.
+ 		 */
+ 		if ( (dvp->v_mount->mnt_flag & MNT_SUIDDIR)
+ 		&& (pdir->i_mode & ISUID)
+ 		&& (pdir->i_uid != cnp->cn_cred->cr_uid)
+ 		&& pdir->i_uid) {
+ 			ip->i_uid = pdir->i_uid;
+ 			mode &= ~07111;
+ #ifdef QUOTA
+ 			/*
+ 			 * make sure the correct user gets charged
+ 			 * for the space.
+ 			 * Quickly knock up a dummy credential for the victim.
+ 			 * XXX This seems to never be accessed out of our
+ 			 * context so a stack variable is ok.
+ 			 */
+ 			ucred.cr_ref = 1
+ 			ucred.cr_uid = ip->i_uid;
+ 			ucred.cr_ngroups = 1
+ 			ucred.cr_groups[0] = pdir->i_gid;
+ 			ucp = *ucred;
+ #endif			I
+ 		} else {
+ 			ip->i_uid = cnp->cn_cred->cr_uid;
+ 		}
+ 	
+ #ifdef QUOTA
+ 		if ((error = getinoquota(ip)) ||
+ 	    	(error = chkiq(ip, 1, ucp, 0))) {
+ 			free(cnp->cn_pnbuf, M_NAMEI);
+ 			VOP_VFREE(tvp, ip->i_number, mode);
+ 			vput(tvp);
+ 			vput(dvp);
+ 			return (error);
+ 		}
+ #endif
+ 	}
+ #else
  	ip->i_uid = cnp->cn_cred->cr_uid;
  #ifdef QUOTA
  	if ((error = getinoquota(ip)) ||
***************
*** 2141,2146 ****
--- 2244,2250 ----
  		vput(dvp);
  		return (error);
  	}
+ #endif
  #endif
  	ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
  	ip->i_mode = mode;



...--end--


 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199711090436.UAA26951>