Module Name:    src
Committed By:   manu
Date:           Wed Sep  3 16:01:45 UTC 2014

Modified Files:
        src/lib/libperfuse: ops.c perfuse.c

Log Message:
Improve POSIX compliance of FUSE filesystems through PERUSE
- access denied is EPERM and not EACCES
- access to file owned by someone else in a sticy-bit directory should
  be allowed for the sticy-bit directory owner
- setting sticky-bit on a non directory should produce EFTYPE
- implement PATHCONF method as much as we can.


To generate a diff of this commit:
cvs rdiff -u -r1.70 -r1.71 src/lib/libperfuse/ops.c
cvs rdiff -u -r1.33 -r1.34 src/lib/libperfuse/perfuse.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libperfuse/ops.c
diff -u src/lib/libperfuse/ops.c:1.70 src/lib/libperfuse/ops.c:1.71
--- src/lib/libperfuse/ops.c:1.70	Fri Aug 29 04:58:40 2014
+++ src/lib/libperfuse/ops.c	Wed Sep  3 16:01:45 2014
@@ -1,4 +1,4 @@
-/*  $NetBSD: ops.c,v 1.70 2014/08/29 04:58:40 manu Exp $ */
+/*  $NetBSD: ops.c,v 1.71 2014/09/03 16:01:45 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
@@ -269,7 +269,7 @@ sticky_access(puffs_cookie_t opc, struct
 	      const struct puffs_cred *pcr)
 {
 	uid_t uid;
-	int sticky, owner;
+	int sticky, owner, parent_owner;
 
 	/*
 	 * This covers the case where the kernel requests a DELETE
@@ -288,9 +288,10 @@ sticky_access(puffs_cookie_t opc, struct
 
 	sticky = puffs_pn_getvap(opc)->va_mode & S_ISTXT;
 	owner = puffs_pn_getvap(targ)->va_uid == uid;
+	parent_owner = puffs_pn_getvap(opc)->va_uid == uid;
 
-	if (sticky && !owner)
-		return EACCES;
+	if (sticky && !owner && !parent_owner)
+		return EPERM;
 
 	return 0;
 }
@@ -1305,7 +1306,7 @@ perfuse_node_mknod(struct puffs_usermoun
 		break;
 	default:	/* VNON, VBLK, VCHR, VBAD */
 		if (!puffs_cred_isjuggernaut(pcn->pcn_cred)) {
-			error = EACCES;
+			error = EPERM;
 			goto out;
 		}
 		break;
@@ -1696,7 +1697,7 @@ perfuse_node_setattr_ttl(struct puffs_us
 	     (vap->va_mtime.tv_sec != (time_t)PUFFS_VNOVAL)) &&
 	    (puffs_access_times(old_va->va_uid, old_va->va_gid,
 				old_va->va_mode, 0, pcr) != 0))
-		return EACCES;
+		return EPERM;
 
 	/*
 	 * Check for permission to change owner and group
@@ -1705,7 +1706,15 @@ perfuse_node_setattr_ttl(struct puffs_us
 	     (vap->va_gid != (gid_t)PUFFS_VNOVAL)) &&
 	    (puffs_access_chown(old_va->va_uid, old_va->va_gid,
 				vap->va_uid, vap->va_gid, pcr)) != 0)
-		return EACCES;
+		return EPERM;
+
+	/*
+	 * Check for sticky bit on non-directory by non root user
+	 */
+	if ((vap->va_mode != (mode_t)PUFFS_VNOVAL) &&
+	    (vap->va_mode & S_ISTXT) && (old_va->va_type != VDIR) &&
+	    !puffs_cred_isjuggernaut(pcr))
+		return EFTYPE;
 
 	/*
 	 * Check for permission to change permissions
@@ -1713,7 +1722,7 @@ perfuse_node_setattr_ttl(struct puffs_us
 	if ((vap->va_mode != (mode_t)PUFFS_VNOVAL) &&
 	    (puffs_access_chmod(old_va->va_uid, old_va->va_gid,
 				old_va->va_type, vap->va_mode, pcr)) != 0)
-		return EACCES;
+		return EPERM;
 	
 	node_ref(opc);
 	
@@ -2877,13 +2886,68 @@ perfuse_node_print(struct puffs_usermoun
 	return 0;
 }
 
-/* ARGSUSED0 */
 int
 perfuse_node_pathconf(struct puffs_usermount *pu, puffs_cookie_t opc,
 	int name, int *retval)
 {
-	DERRX(EX_SOFTWARE, "%s: UNIMPLEMENTED (FATAL)", __func__);
-	return 0;
+	perfuse_msg_t *pm;
+	struct perfuse_state *ps;
+	struct fuse_statfs_out *fso;
+	int error = 0;
+
+	/*
+	 * Static values copied from UFS 
+	 * in src/sys/ufs/ufs/ufs_vnops.c
+	 */
+	switch (name) {
+	case _PC_LINK_MAX:
+		*retval = LINK_MAX;
+		break;
+	case _PC_PATH_MAX:
+		*retval = PATH_MAX;
+		break;
+	case _PC_PIPE_BUF:
+		*retval = PIPE_BUF;
+		break;
+	case _PC_CHOWN_RESTRICTED:
+		*retval = 1;
+		break;
+	case _PC_NO_TRUNC:
+		*retval = 1;
+		break;
+	case _PC_SYNC_IO:
+		*retval = 1;
+		break;
+	case _PC_FILESIZEBITS:
+		*retval = 42;
+		break;
+	case _PC_SYMLINK_MAX:
+		*retval = MAXPATHLEN;
+		break;
+	case _PC_2_SYMLINKS:
+		*retval = 1;
+		break;
+	case _PC_NAME_MAX:
+		ps = puffs_getspecific(pu);
+		pm = ps->ps_new_msg(pu, opc, FUSE_STATFS, 0, NULL);
+
+		error = xchg_msg(pu, opc, pm, sizeof(*fso), wait_reply);
+		if (error != 0)
+			return error;
+
+		fso = GET_OUTPAYLOAD(ps, pm, fuse_statfs_out);
+		*retval = fso->st.namelen;
+
+		ps->ps_destroy_msg(pm);
+	
+		break;
+	default:
+		DWARN("Unimplemented pathconf for name = %d", name);
+		error = ENOSYS;
+		break;
+	}
+
+	return error;
 }
 
 int

Index: src/lib/libperfuse/perfuse.c
diff -u src/lib/libperfuse/perfuse.c:1.33 src/lib/libperfuse/perfuse.c:1.34
--- src/lib/libperfuse/perfuse.c:1.33	Sat Aug 16 16:31:15 2014
+++ src/lib/libperfuse/perfuse.c	Wed Sep  3 16:01:45 2014
@@ -1,4 +1,4 @@
-/*  $NetBSD: perfuse.c,v 1.33 2014/08/16 16:31:15 manu Exp $ */
+/*  $NetBSD: perfuse.c,v 1.34 2014/09/03 16:01:45 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
@@ -483,6 +483,7 @@ perfuse_init(struct perfuse_callbacks *p
 	PUFFSOP_SET(pops, perfuse, node, reclaim);
 	PUFFSOP_SET(pops, perfuse, node, inactive);
 	PUFFSOP_SET(pops, perfuse, node, print);
+	PUFFSOP_SET(pops, perfuse, node, pathconf);
 	PUFFSOP_SET(pops, perfuse, node, advlock);
 	PUFFSOP_SET(pops, perfuse, node, read);
 	PUFFSOP_SET(pops, perfuse, node, write);

Reply via email to