PERFORCE change 180147 for review

Efstratios Karatzas gpf at FreeBSD.org
Wed Jun 23 13:37:47 UTC 2010


http://p4web.freebsd.org/@@180147?ac=10

Change 180147 by gpf at gpf_desktop on 2010/06/23 13:36:55

	I'm back in the game!
	
	experimental nfs server:
	
	- spent some time trying to figure out the best way to go about 
	auditing paths in fs/nfsserver. I ended up taking advantage of 
	the chokepoints that Rick's code provides us; this way I avoid 
	passing extra arguments to the pseudosyscalls and messing his code.
	I'll keep working on that in the next few days.
	- fixed bogus behavior of my patch in setattr
	- also changed how nfs rpc numbers are mapped to audit events,
	this will prove useful when I introduce nfsv4 to audit
	- also figured out how and why vn_fullpath() kernel panics in my 
	nfs patches. Turns out my current nfs patches are ok in regards to that 
	matter, more on that in my weekly report; perhaps I'll also send 
	an email to hackers@ although I doubt it'll get any attention, anyhoo

Affected files ...

.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/nfsserver/nfs_nfsdserv.c#4 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/nfsserver/nfs_nfsdsocket.c#4 edit
.. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/security/audit/audit.c#6 edit

Differences ...

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/nfsserver/nfs_nfsdserv.c#4 (text+ko) ====

@@ -241,9 +241,7 @@
 	nfsattrbit_t attrbits, retbits;
 	nfsv4stateid_t stateid;
 	NFSACL_T *aclp = NULL;
-
-	if (vp != NULL)
-		AUDIT_ARG_VNODE1(vp);
+	
 	if (nd->nd_repstat) {
 		nfsrv_wcc(nd, preat_ret, &nva2, postat_ret, &nva);
 		return (0);
@@ -386,6 +384,7 @@
 		if (!nd->nd_repstat)
 			nd->nd_repstat = postat_ret;
 	}
+	AUDIT_ARG_VNODE1(vp);
 	vput(vp);
 #ifdef NFS4_ACL_EXTATTR_NAME
 	acl_free(aclp);
@@ -398,6 +397,7 @@
 		nfsrv_fillattr(nd, &nva);
 	return (0);
 nfsmout:
+	AUDIT_ARG_VNODE1(vp);
 	vput(vp);
 #ifdef NFS4_ACL_EXTATTR_NAME
 	acl_free(aclp);

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/fs/nfsserver/nfs_nfsdsocket.c#4 (text+ko) ====

@@ -345,6 +345,113 @@
 	NFSV4OP_COMMIT,
 };
 
+/* 
+ * XXXgpf: should relocate them someplace else
+ * I just dont know where:S 
+ */
+#define PARENTHINT 0x0001
+#define EXHAUSTSEARCH 0x0002
+#define WANTNAME 0x0004
+
+/*
+ * XXXgpf: should probably relocate this function somewhere else as it's going to be called from various 
+ * places in fs/nfsserver/
+ * 
+ * Do our best to acquire 'a' working path for vp
+ * 
+ * vp		-	vnode in question
+ * dvp		-	directory with vp as a child
+ * fname	-	name used to reference vp inside dvp
+ * fhp		-	file handle for vp
+ * n		-	AUDIT_ARG_UPATH1 or AUDIT_ARG_UPATH2
+ */
+static void
+nfsrv_auditpath(struct vnode *vp, struct vnode *dvp, char *fname, fhandle_t *fhp, int n)
+{
+	char path[PATH_MAX];
+	struct thread *td;
+	char *fullpath, *freepath;
+	char success;
+	
+	if (!AUDITING_TD(curthread))
+		return;
+
+	td = curthread;
+	freepath = NULL;
+	success = 0;
+	
+	/* try to find the path through vp */
+	if (vp != NULL) {
+		/* try the cache */
+		vn_fullpath_global(td, vp, &fullpath, &freepath);
+		if (freepath != NULL) {
+			success = 1;
+			goto out;
+		}
+
+		/* if our cache fails us */
+		if (fhp != NULL && vp->v_mount != NULL) {
+			uint64_t parent_hint;
+			/* get the hint stored inside the file handle */
+			VFS_FHHINT(vp->v_mount, &fhp->fh_fid, &parent_hint);
+			vn_fullpath_nocache(vp, &fullpath, &freepath,
+				parent_hint, PARENTHINT | WANTNAME);
+			if (freepath != NULL) {
+				success = 1;
+				goto out;
+			}
+		}
+	}
+
+	/* try to find the path through dvp and the component name used to reference vp */
+	if (dvp != NULL && fname != NULL) {
+		/* try the cache */
+		vn_fullpath_global(td, dvp, &fullpath, &freepath);
+		if (freepath != NULL) {
+			snprintf(path, sizeof(path), "%s/%s", fullpath, fname);
+			fullpath = path;
+			success = 1;
+			goto out;
+		}
+
+		/* if our cache fails us */
+		vn_fullpath_nocache(dvp, &fullpath, &freepath,
+			0, WANTNAME);
+		if (freepath != NULL) {
+			snprintf(path, sizeof(path), "%s/%s", fullpath, fname);
+			fullpath = path;
+			success = 1;
+			goto out;
+		}
+	}
+	
+	/* last resort, just save the name used to reference the file in question */
+	if (fname != NULL) {
+		strlcpy(path, fname, sizeof(path));
+		fullpath = path;
+		success = 1;
+	}
+
+out:		
+	if (success) {
+		switch (n) {
+		case 1:
+			AUDIT_ARG_UPATH1(td, fullpath);
+			break;
+		case 2:
+			AUDIT_ARG_UPATH2(td, fullpath);
+			break;
+		default:
+			AUDIT_ARG_UPATH1(td, fullpath);
+			break;
+		}
+	}
+	
+	if (freepath != NULL) {
+		free(freepath, M_TEMP);
+	}
+}
+
 /*
  * Do an RPC. Basically, get the file handles translated to vnode pointers
  * and then call the appropriate server routine. The server routines are
@@ -442,13 +549,24 @@
 			if (vp)
 				NFSVOPUNLOCK(vp, 0, p);
 			error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
-			    vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes);
+			    vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes);			
 		} else if (nfs_retfh[nd->nd_procnum] == 2) {
 			error = (*(nfsrv3_procs2[nd->nd_procnum]))(nd, isdgram,
 			    vp, NULL, p, &nes, NULL);
 		} else {
+			if (vp != NULL)
+				vref(vp);
 			error = (*(nfsrv3_procs0[nd->nd_procnum]))(nd, isdgram,
 			    vp, p, &nes);
+			if (vp != NULL) {
+				if (nd->nd_procnum != NFSPROC_CREATE && 
+				    nd->nd_procnum != NFSPROC_RMDIR && 
+				    nd->nd_procnum != NFSPROC_REMOVE) {
+					nfsrv_auditpath(vp, NULL, NULL, 
+						(fhandle_t *)fh.nfsrvfh_data, 1);
+				}
+				vrele(vp);
+			}
 		}
 		AUDIT_NFS_EXIT(error, curthread);
 		if (mp) {

==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/security/audit/audit.c#6 (text) ====

@@ -598,128 +598,40 @@
 int
 audit_nfs_proc_to_event(unsigned int proc, au_event_t *event)
 {
-	switch (proc) {
-	case 0:
-		/* nfsrv_null */
-		*event = AUE_NFS_NULL;
-		break;
-		
-	case 1:
-		/* nfsrv_getattr */
-		*event = AUE_NFS_GETATTR;
-		break;
-		
-	case 2:
-		/* nfsrv_setattr */
-		*event = AUE_NFS_SETATTR;
-		break;
-		
-	case 3:
-		/* nfsrv_lookup */
-		*event = AUE_NFS_LOOKUP;
-		break;
-		
-	case 4:
-		/* nfsrv3_access */
-		*event = AUE_NFS_ACCESS;
-		break;
-		
-	case 5:
-		/* nfsrv_readlink */
-		*event = AUE_NFS_READLINK;
-		break;
-		
-	case 6:
-		/* nfsrv_read */
-		*event = AUE_NFS_READ;
-		break;
-		
-	case 7:
-		/* nfsrv_write */
-		*event = AUE_NFS_WRITE;
-		break;
-
-	case 8:
-		/* nfsrv_create */
-		*event = AUE_NFS_CREATE;
-		break;
-		
-	case 9:
-		/* nfsrv_mkdir */
-		*event = AUE_NFS_MKDIR;
-		break;
-		
-	case 10:
-		/* nfsrv_symlink */
-		*event = AUE_NFS_SYMLINK;
-		break;
-		
-	case 11:
-		/*  nfsrv_mknod */
-		*event = AUE_NFS_MKNODE;
-		break;
-		
-	case 12:
-		/*  nfsrv_remove */
-		*event = AUE_NFS_REMOVE;
-		break;
-		
-	case 13:
-		/* nfsrv_rmdir */
-		*event = AUE_NFS_RMDIR;
-		break;
-		
-	case 14:
-		/* nfsrv_rename */
-		*event = AUE_NFS_RENAME;
-		break;
-		
-	case 15:
-		/* nfsrv_link */
-		*event = AUE_NFS_LINK;
-		break;
-		
-	case 16:
-		/* nfsrv_readdir */
-		*event = AUE_NFS_READDIR;
-		break;
-		
-	case 17:
-		/* nfsrv_readdirplus */
-		*event = AUE_NFS_READDIR_PLUS;
-		break;
-		
-	case 18:
-		/* nfsrv_statfs */
-		*event = AUE_NFS_STATFS;
-		break;
-		
-	case 19:
-		/* nfsrv_fsinfo */
-		*event = AUE_NFS_FSINFO;
-		break;
-		
-	case 20:
-		/* nfsrv_pathconf */
-		*event = AUE_NFS_PATHCONF;
-		break;
-		
-	case 21:
-		/* nfsrv_commit */
-		*event = AUE_NFS_COMMIT;
-		break;
-		
-	case 22:
-		/* nfsrv_noop */
-		*event = AUE_NFS_NOOP;
-		break;		
+	au_event_t nfsv3toevent[] = {
+		AUE_NFS_NULL,
+		AUE_NFS_GETATTR,
+		AUE_NFS_SETATTR,
+		AUE_NFS_LOOKUP,
+		AUE_NFS_ACCESS,
+		AUE_NFS_READLINK,
+		AUE_NFS_READ,
+		AUE_NFS_WRITE,
+		AUE_NFS_CREATE,
+		AUE_NFS_MKDIR,
+		AUE_NFS_SYMLINK,
+		AUE_NFS_MKNODE,
+		AUE_NFS_REMOVE,
+		AUE_NFS_RMDIR,
+		AUE_NFS_RENAME,
+		AUE_NFS_LINK,
+		AUE_NFS_READDIR,
+		AUE_NFS_READDIR_PLUS,
+		AUE_NFS_STATFS,
+		AUE_NFS_FSINFO,
+		AUE_NFS_PATHCONF,
+		AUE_NFS_COMMIT,
+		AUE_NFS_NOOP,		
+	};
+	static int nfs_v3nprocs = sizeof(nfsv3toevent) / sizeof(au_event_t);
 	
-	default:		
-		*event = AUE_NFS_NULL;
-		return 1; /* unmatched */
+	if (proc < nfs_v3nprocs) {
+		*event = nfsv3toevent[proc];
+		return 0;
+	}
+	else {
+		return EINVAL;
 	}
-	
-	return 0; /* matched */
 }
 
 /*
@@ -736,14 +648,19 @@
 	au_class_t class;
 	au_event_t event;
 	au_id_t auid;
+	int error;
 	
 	KASSERT(td->td_ar == NULL, ("audit_nfs_enter: td->td_ar != NULL"));
 	KASSERT((td->td_pflags & TDP_AUDITREC) == 0,
 	    ("audit_nfs_enter: TDP_AUDITREC set"));
+
+	error = audit_nfs_proc_to_event(proc, &event);
+	if (error) {
+		td->td_ar = NULL;
+		return;
+	}
 	
-	/* XXXgpf: perhaps log a failure to match a rpc to an audit event? */
-	audit_nfs_proc_to_event(proc, &event);
-	
+	/* XXXgpf: for debuging, nevermind */
 	printf("audit_nfs_enter: procedure = %d\n"
 	       "audit_nfs_enter: event = %d\n", proc, event);
 	


More information about the p4-projects mailing list