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