It is required by VOP_CREATE, VOP_MKNOD, VOP_SYMLINK and VOP_MKDIR
that va_mode of the supplied attributes is filled in with a valid file mode (i.e not VNOVAL, and only ALLPERM bits set). However, some NFS server op functions didn't guarantee this for all possible request messages: If a V3 client chose not include to a mode specification, we could end up creating an ffs inode with mode 0177777, requiring a manual fsck on the next reboot. Fix this by setting va_mode to 0 before calling the VOP if a mode hasn't been supplied by the client. In nfsrv_symlink(), S_IFMT bits supplied by a V2 client could end up in the va_mode passed to VOP_SYMLINK with similar effects. We now use the macro nfstov_mode() to correctly mask the bits.
This commit is contained in:
parent
900716eeea
commit
8a919282a5
@ -1679,8 +1679,6 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
|
||||
cp = nfsm_dissect(caddr_t, NFSX_V3CREATEVERF);
|
||||
bcopy(cp, cverf, NFSX_V3CREATEVERF);
|
||||
exclusive_flag = 1;
|
||||
if (nd.ni_vp == NULL)
|
||||
vap->va_mode = 0;
|
||||
break;
|
||||
};
|
||||
vap->va_type = VREG;
|
||||
@ -1715,6 +1713,8 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
|
||||
* nd.ni_vp will also be non-NULL in that case.
|
||||
*/
|
||||
if (nd.ni_vp == NULL) {
|
||||
if (vap->va_mode == (mode_t)VNOVAL)
|
||||
vap->va_mode = 0;
|
||||
if (vap->va_type == VREG || vap->va_type == VSOCK) {
|
||||
error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
|
||||
if (error)
|
||||
@ -1938,6 +1938,8 @@ nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
|
||||
goto out;
|
||||
}
|
||||
vap->va_type = vtyp;
|
||||
if (vap->va_mode == (mode_t)VNOVAL)
|
||||
vap->va_mode = 0;
|
||||
if (vtyp == VSOCK) {
|
||||
vrele(nd.ni_startdir);
|
||||
nd.ni_startdir = NULL;
|
||||
@ -2560,7 +2562,7 @@ nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
|
||||
nfsm_mtouio(&io, len2);
|
||||
if (!v3) {
|
||||
sp = nfsm_dissect(struct nfsv2_sattr *, NFSX_V2SATTR);
|
||||
vap->va_mode = fxdr_unsigned(u_int16_t, sp->sa_mode);
|
||||
vap->va_mode = nfstov_mode(sp->sa_mode);
|
||||
}
|
||||
*(pathcp + len2) = '\0';
|
||||
if (nd.ni_vp) {
|
||||
@ -2572,6 +2574,8 @@ nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
|
||||
* issue symlink op. SAVESTART is set so the underlying path component
|
||||
* is only freed by the VOP if an error occurs.
|
||||
*/
|
||||
if (vap->va_mode == (mode_t)VNOVAL)
|
||||
vap->va_mode = 0;
|
||||
error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap, pathcp);
|
||||
if (error)
|
||||
NDFREE(&nd, NDF_ONLY_PNBUF);
|
||||
@ -2755,6 +2759,8 @@ nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
|
||||
* component is freed by the VOP call. This will fill-in
|
||||
* nd.ni_vp, reference, and exclusively lock it.
|
||||
*/
|
||||
if (vap->va_mode == (mode_t)VNOVAL)
|
||||
vap->va_mode = 0;
|
||||
error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
|
||||
NDFREE(&nd, NDF_ONLY_PNBUF);
|
||||
vpexcl = 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user