Date: Wed, 23 Jun 2010 13:37:46 GMT From: Efstratios Karatzas <gpf@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 180147 for review Message-ID: <201006231337.o5NDbkFp016685@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@180147?ac=10 Change 180147 by gpf@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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201006231337.o5NDbkFp016685>