summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/compat/ndis/subr_ndis.c29
-rw-r--r--sys/kern/kern_linker.c13
-rw-r--r--sys/kern/link_elf.c6
-rw-r--r--sys/kern/link_elf_obj.c6
4 files changed, 36 insertions, 18 deletions
diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c
index 40ff543..3ed857b 100644
--- a/sys/compat/ndis/subr_ndis.c
+++ b/sys/compat/ndis/subr_ndis.c
@@ -2925,7 +2925,7 @@ NdisOpenFile(status, filehandle, filelength, filename, highestaddr)
char *afilename = NULL;
struct thread *td = curthread;
struct nameidata nd;
- int flags, error;
+ int flags, error, vfslocked;
struct vattr vat;
struct vattr *vap = &vat;
ndis_fh *fh;
@@ -2998,8 +2998,6 @@ NdisOpenFile(status, filehandle, filelength, filename, highestaddr)
snprintf(path, MAXPATHLEN, "%s/%s", ndis_filepath, afilename);
- mtx_lock(&Giant);
-
/* Some threads don't have a current working directory. */
if (td->td_proc->p_fd->fd_rdir == NULL)
@@ -3007,12 +3005,11 @@ NdisOpenFile(status, filehandle, filelength, filename, highestaddr)
if (td->td_proc->p_fd->fd_cdir == NULL)
td->td_proc->p_fd->fd_cdir = rootvnode;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td);
+ NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, path, td);
flags = FREAD;
error = vn_open(&nd, &flags, 0, -1);
if (error) {
- mtx_unlock(&Giant);
*status = NDIS_STATUS_FILE_NOT_FOUND;
ExFreePool(fh);
printf("NDIS: open file %s failed: %d\n", path, error);
@@ -3020,6 +3017,7 @@ NdisOpenFile(status, filehandle, filelength, filename, highestaddr)
free(afilename, M_DEVBUF);
return;
}
+ vfslocked = NDHASGIANT(&nd);
ExFreePool(path);
@@ -3028,7 +3026,7 @@ NdisOpenFile(status, filehandle, filelength, filename, highestaddr)
/* Get the file size. */
VOP_GETATTR(nd.ni_vp, vap, td->td_ucred, td);
VOP_UNLOCK(nd.ni_vp, 0, td);
- mtx_unlock(&Giant);
+ VFS_UNLOCK_GIANT(vfslocked);
fh->nf_vp = nd.ni_vp;
fh->nf_map = NULL;
@@ -3050,7 +3048,8 @@ NdisMapFile(status, mappedbuffer, filehandle)
struct thread *td = curthread;
linker_file_t lf;
caddr_t kldstart;
- int error, resid;
+ int error, resid, vfslocked;
+ struct vnode *vp;
if (filehandle == NULL) {
*status = NDIS_STATUS_FAILURE;
@@ -3088,10 +3087,11 @@ NdisMapFile(status, mappedbuffer, filehandle)
return;
}
- mtx_lock(&Giant);
- error = vn_rdwr(UIO_READ, fh->nf_vp, fh->nf_map, fh->nf_maplen, 0,
+ vp = fh->nf_vp;
+ vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ error = vn_rdwr(UIO_READ, vp, fh->nf_map, fh->nf_maplen, 0,
UIO_SYSSPACE, 0, td->td_ucred, NOCRED, &resid, td);
- mtx_unlock(&Giant);
+ VFS_UNLOCK_GIANT(vfslocked);
if (error)
*status = NDIS_STATUS_FAILURE;
@@ -3126,6 +3126,8 @@ NdisCloseFile(filehandle)
{
struct thread *td = curthread;
ndis_fh *fh;
+ int vfslocked;
+ struct vnode *vp;
if (filehandle == NULL)
return;
@@ -3141,9 +3143,10 @@ NdisCloseFile(filehandle)
return;
if (fh->nf_type == NDIS_FH_TYPE_VFS) {
- mtx_lock(&Giant);
- vn_close(fh->nf_vp, FREAD, td->td_ucred, td);
- mtx_unlock(&Giant);
+ vp = fh->nf_vp;
+ vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ vn_close(vp, FREAD, td->td_ucred, td);
+ VFS_UNLOCK_GIANT(vfslocked);
}
fh->nf_vp = NULL;
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
index 6eb62b6..986f34a 100644
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sx.h>
#include <sys/mac.h>
#include <sys/module.h>
+#include <sys/mount.h>
#include <sys/linker.h>
#include <sys/fcntl.h>
#include <sys/libkern.h>
@@ -1483,7 +1484,7 @@ linker_lookup_file(const char *path, int pathlen, const char *name,
struct nameidata nd;
struct thread *td = curthread; /* XXX */
char *result, **cpp, *sep;
- int error, len, extlen, reclen, flags;
+ int error, len, extlen, reclen, flags, vfslocked;
enum vtype type;
extlen = 0;
@@ -1504,16 +1505,18 @@ linker_lookup_file(const char *path, int pathlen, const char *name,
* Attempt to open the file, and return the path if
* we succeed and it's a regular file.
*/
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, result, td);
+ NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, result, td);
flags = FREAD;
error = vn_open(&nd, &flags, 0, -1);
if (error == 0) {
+ vfslocked = NDHASGIANT(&nd);
NDFREE(&nd, NDF_ONLY_PNBUF);
type = nd.ni_vp->v_type;
if (vap)
VOP_GETATTR(nd.ni_vp, vap, td->td_ucred, td);
VOP_UNLOCK(nd.ni_vp, 0, td);
vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
+ VFS_UNLOCK_GIANT(vfslocked);
if (type == VREG)
return (result);
}
@@ -1541,6 +1544,7 @@ linker_hints_lookup(const char *path, int pathlen, const char *modname,
u_char *hints = NULL;
u_char *cp, *recptr, *bufend, *result, *best, *pathbuf, *sep;
int error, ival, bestver, *intp, reclen, found, flags, clen, blen;
+ int vfslocked = 0;
result = NULL;
bestver = found = 0;
@@ -1552,11 +1556,12 @@ linker_hints_lookup(const char *path, int pathlen, const char *modname,
snprintf(pathbuf, reclen, "%.*s%s%s", pathlen, path, sep,
linker_hintfile);
- NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, pathbuf, td);
+ NDINIT(&nd, LOOKUP, NOFOLLOW | MPSAFE, UIO_SYSSPACE, pathbuf, td);
flags = FREAD;
error = vn_open(&nd, &flags, 0, -1);
if (error)
goto bad;
+ vfslocked = NDHASGIANT(&nd);
NDFREE(&nd, NDF_ONLY_PNBUF);
if (nd.ni_vp->v_type != VREG)
goto bad;
@@ -1580,6 +1585,7 @@ linker_hints_lookup(const char *path, int pathlen, const char *modname,
goto bad;
VOP_UNLOCK(nd.ni_vp, 0, td);
vn_close(nd.ni_vp, FREAD, cred, td);
+ VFS_UNLOCK_GIANT(vfslocked);
nd.ni_vp = NULL;
if (reclen != 0) {
printf("can't read %d\n", reclen);
@@ -1648,6 +1654,7 @@ bad:
if (nd.ni_vp != NULL) {
VOP_UNLOCK(nd.ni_vp, 0, td);
vn_close(nd.ni_vp, FREAD, cred, td);
+ VFS_UNLOCK_GIANT(vfslocked);
}
/*
* If nothing found or hints is absent - fallback to the old
diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c
index 7b3f1ab..14b9c2e 100644
--- a/sys/kern/link_elf.c
+++ b/sys/kern/link_elf.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mac.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
+#include <sys/mount.h>
#include <sys/proc.h>
#include <sys/namei.h>
#include <sys/fcntl.h>
@@ -556,17 +557,19 @@ link_elf_load_file(linker_class_t cls, const char* filename,
int symstrindex;
int symcnt;
int strcnt;
+ int vfslocked;
GIANT_REQUIRED;
shdr = NULL;
lf = NULL;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, td);
+ NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, filename, td);
flags = FREAD;
error = vn_open(&nd, &flags, 0, -1);
if (error)
return error;
+ vfslocked = NDHASGIANT(&nd);
NDFREE(&nd, NDF_ONLY_PNBUF);
#ifdef MAC
error = mac_check_kld_load(curthread->td_ucred, nd.ni_vp);
@@ -859,6 +862,7 @@ out:
free(firstpage, M_LINKER);
VOP_UNLOCK(nd.ni_vp, 0, td);
vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
+ VFS_UNLOCK_GIANT(vfslocked);
return error;
}
diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c
index de43b7a..5a10298 100644
--- a/sys/kern/link_elf_obj.c
+++ b/sys/kern/link_elf_obj.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mac.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
+#include <sys/mount.h>
#include <sys/proc.h>
#include <sys/namei.h>
#include <sys/fcntl.h>
@@ -393,6 +394,7 @@ link_elf_load_file(linker_class_t cls, const char *filename,
int nsym;
int pb, rl, ra;
int alignmask;
+ int vfslocked;
GIANT_REQUIRED;
@@ -401,11 +403,12 @@ link_elf_load_file(linker_class_t cls, const char *filename,
mapsize = 0;
hdr = NULL;
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, td);
+ NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, filename, td);
flags = FREAD;
error = vn_open(&nd, &flags, 0, -1);
if (error)
return error;
+ vfslocked = NDHASGIANT(&nd);
NDFREE(&nd, NDF_ONLY_PNBUF);
#ifdef MAC
error = mac_check_kld_load(td->td_ucred, nd.ni_vp);
@@ -788,6 +791,7 @@ out:
free(hdr, M_LINKER);
VOP_UNLOCK(nd.ni_vp, 0, td);
vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
+ VFS_UNLOCK_GIANT(vfslocked);
return error;
}
OpenPOWER on IntegriCloud