diff options
| -rw-r--r-- | fs/nfs/inode.c | 8 | ||||
| -rw-r--r-- | fs/nfs/internal.h | 7 | ||||
| -rw-r--r-- | fs/nfs/namespace.c | 113 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 14 | ||||
| -rw-r--r-- | fs/nfs/nfs4xdr.c | 11 | ||||
| -rw-r--r-- | include/linux/nfs_xdr.h | 1 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/gss_mech_switch.c | 22 |
7 files changed, 165 insertions, 11 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 01768e5e2c9..058d7d63e56 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -254,7 +254,9 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
| 254 | struct inode *inode = ERR_PTR(-ENOENT); | 254 | struct inode *inode = ERR_PTR(-ENOENT); |
| 255 | unsigned long hash; | 255 | unsigned long hash; |
| 256 | 256 | ||
| 257 | if ((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0) | 257 | nfs_attr_check_mountpoint(sb, fattr); |
| 258 | |||
| 259 | if ((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0 && (fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT) == 0) | ||
| 258 | goto out_no_inode; | 260 | goto out_no_inode; |
| 259 | if ((fattr->valid & NFS_ATTR_FATTR_TYPE) == 0) | 261 | if ((fattr->valid & NFS_ATTR_FATTR_TYPE) == 0) |
| 260 | goto out_no_inode; | 262 | goto out_no_inode; |
| @@ -298,8 +300,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
| 298 | if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS)) | 300 | if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS)) |
| 299 | set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); | 301 | set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags); |
| 300 | /* Deal with crossing mountpoints */ | 302 | /* Deal with crossing mountpoints */ |
| 301 | if ((fattr->valid & NFS_ATTR_FATTR_FSID) | 303 | if (fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT || |
| 302 | && !nfs_fsid_equal(&NFS_SB(sb)->fsid, &fattr->fsid)) { | 304 | fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) { |
| 303 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) | 305 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) |
| 304 | inode->i_op = &nfs_referral_inode_operations; | 306 | inode->i_op = &nfs_referral_inode_operations; |
| 305 | else | 307 | else |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 1ec5d0662ed..345d86b90e2 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
| @@ -39,6 +39,12 @@ static inline int nfs4_has_persistent_session(const struct nfs_client *clp) | |||
| 39 | return 0; | 39 | return 0; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | static inline void nfs_attr_check_mountpoint(struct super_block *parent, struct nfs_fattr *fattr) | ||
| 43 | { | ||
| 44 | if (!nfs_fsid_equal(&NFS_SB(parent)->fsid, &fattr->fsid)) | ||
| 45 | fattr->valid |= NFS_ATTR_FATTR_MOUNTPOINT; | ||
| 46 | } | ||
| 47 | |||
| 42 | struct nfs_clone_mount { | 48 | struct nfs_clone_mount { |
| 43 | const struct super_block *sb; | 49 | const struct super_block *sb; |
| 44 | const struct dentry *dentry; | 50 | const struct dentry *dentry; |
| @@ -214,6 +220,7 @@ extern const u32 nfs41_maxwrite_overhead; | |||
| 214 | /* nfs4proc.c */ | 220 | /* nfs4proc.c */ |
| 215 | #ifdef CONFIG_NFS_V4 | 221 | #ifdef CONFIG_NFS_V4 |
| 216 | extern struct rpc_procinfo nfs4_procedures[]; | 222 | extern struct rpc_procinfo nfs4_procedures[]; |
| 223 | void nfs_fixup_secinfo_attributes(struct nfs_fattr *, struct nfs_fh *); | ||
| 217 | #endif | 224 | #endif |
| 218 | 225 | ||
| 219 | extern int nfs4_init_ds_session(struct nfs_client *clp); | 226 | extern int nfs4_init_ds_session(struct nfs_client *clp); |
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index b02720864de..ad92bf731ff 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/string.h> | 15 | #include <linux/string.h> |
| 16 | #include <linux/sunrpc/clnt.h> | 16 | #include <linux/sunrpc/clnt.h> |
| 17 | #include <linux/vfs.h> | 17 | #include <linux/vfs.h> |
| 18 | #include <linux/sunrpc/gss_api.h> | ||
| 18 | #include "internal.h" | 19 | #include "internal.h" |
| 19 | 20 | ||
| 20 | #define NFSDBG_FACILITY NFSDBG_VFS | 21 | #define NFSDBG_FACILITY NFSDBG_VFS |
| @@ -27,7 +28,8 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ; | |||
| 27 | 28 | ||
| 28 | static struct vfsmount *nfs_do_submount(struct dentry *dentry, | 29 | static struct vfsmount *nfs_do_submount(struct dentry *dentry, |
| 29 | struct nfs_fh *fh, | 30 | struct nfs_fh *fh, |
| 30 | struct nfs_fattr *fattr); | 31 | struct nfs_fattr *fattr, |
| 32 | rpc_authflavor_t authflavor); | ||
| 31 | 33 | ||
| 32 | /* | 34 | /* |
| 33 | * nfs_path - reconstruct the path given an arbitrary dentry | 35 | * nfs_path - reconstruct the path given an arbitrary dentry |
| @@ -116,6 +118,100 @@ Elong: | |||
| 116 | return ERR_PTR(-ENAMETOOLONG); | 118 | return ERR_PTR(-ENAMETOOLONG); |
| 117 | } | 119 | } |
| 118 | 120 | ||
| 121 | #ifdef CONFIG_NFS_V4 | ||
| 122 | static rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors, struct inode *inode) | ||
| 123 | { | ||
| 124 | struct gss_api_mech *mech; | ||
| 125 | struct xdr_netobj oid; | ||
| 126 | int i; | ||
| 127 | rpc_authflavor_t pseudoflavor = RPC_AUTH_UNIX; | ||
| 128 | |||
| 129 | for (i = 0; i < flavors->num_flavors; i++) { | ||
| 130 | struct nfs4_secinfo_flavor *flavor; | ||
| 131 | flavor = &flavors->flavors[i]; | ||
| 132 | |||
| 133 | if (flavor->flavor == RPC_AUTH_NULL || flavor->flavor == RPC_AUTH_UNIX) { | ||
| 134 | pseudoflavor = flavor->flavor; | ||
| 135 | break; | ||
| 136 | } else if (flavor->flavor == RPC_AUTH_GSS) { | ||
| 137 | oid.len = flavor->gss.sec_oid4.len; | ||
| 138 | oid.data = flavor->gss.sec_oid4.data; | ||
| 139 | mech = gss_mech_get_by_OID(&oid); | ||
| 140 | if (!mech) | ||
| 141 | continue; | ||
| 142 | pseudoflavor = gss_svc_to_pseudoflavor(mech, flavor->gss.service); | ||
| 143 | gss_mech_put(mech); | ||
| 144 | break; | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | return pseudoflavor; | ||
| 149 | } | ||
| 150 | |||
| 151 | static rpc_authflavor_t nfs_negotiate_security(const struct dentry *parent, const struct dentry *dentry) | ||
| 152 | { | ||
| 153 | int status = 0; | ||
| 154 | struct page *page; | ||
| 155 | struct nfs4_secinfo_flavors *flavors; | ||
| 156 | int (*secinfo)(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *); | ||
| 157 | rpc_authflavor_t flavor = RPC_AUTH_UNIX; | ||
| 158 | |||
| 159 | secinfo = NFS_PROTO(parent->d_inode)->secinfo; | ||
| 160 | if (secinfo != NULL) { | ||
| 161 | page = alloc_page(GFP_KERNEL); | ||
| 162 | if (!page) { | ||
| 163 | status = -ENOMEM; | ||
| 164 | goto out; | ||
| 165 | } | ||
| 166 | flavors = page_address(page); | ||
| 167 | status = secinfo(parent->d_inode, &dentry->d_name, flavors); | ||
| 168 | flavor = nfs_find_best_sec(flavors, dentry->d_inode); | ||
| 169 | put_page(page); | ||
| 170 | } | ||
| 171 | |||
| 172 | return flavor; | ||
| 173 | |||
| 174 | out: | ||
| 175 | status = -ENOMEM; | ||
| 176 | return status; | ||
| 177 | } | ||
| 178 | |||
| 179 | static rpc_authflavor_t nfs_lookup_with_sec(struct nfs_server *server, struct dentry *parent, | ||
| 180 | struct dentry *dentry, struct path *path, | ||
| 181 | struct nfs_fh *fh, struct nfs_fattr *fattr) | ||
| 182 | { | ||
| 183 | rpc_authflavor_t flavor; | ||
| 184 | struct rpc_clnt *clone; | ||
| 185 | struct rpc_auth *auth; | ||
| 186 | int err; | ||
| 187 | |||
| 188 | flavor = nfs_negotiate_security(parent, path->dentry); | ||
| 189 | if (flavor < 0) | ||
| 190 | goto out; | ||
| 191 | clone = rpc_clone_client(server->client); | ||
| 192 | auth = rpcauth_create(flavor, clone); | ||
| 193 | if (!auth) { | ||
| 194 | flavor = -EIO; | ||
| 195 | goto out; | ||
| 196 | } | ||
| 197 | err = server->nfs_client->rpc_ops->lookup(clone, parent->d_inode, | ||
| 198 | &path->dentry->d_name, | ||
| 199 | fh, fattr); | ||
| 200 | if (err < 0) | ||
| 201 | flavor = err; | ||
| 202 | out: | ||
| 203 | return flavor; | ||
| 204 | } | ||
| 205 | #else /* CONFIG_NFS_V4 */ | ||
| 206 | static inline rpc_authflavor_t nfs_lookup_with_sec(struct nfs_server *server, | ||
| 207 | struct dentry *parent, struct dentry *dentry, | ||
| 208 | struct path *path, struct nfs_fh *fh, | ||
| 209 | struct nfs_fattr *fattr) | ||
| 210 | { | ||
| 211 | return -EPERM; | ||
| 212 | } | ||
| 213 | #endif /* CONFIG_NFS_V4 */ | ||
| 214 | |||
| 119 | /* | 215 | /* |
| 120 | * nfs_d_automount - Handle crossing a mountpoint on the server | 216 | * nfs_d_automount - Handle crossing a mountpoint on the server |
| 121 | * @path - The mountpoint | 217 | * @path - The mountpoint |
| @@ -136,6 +232,7 @@ struct vfsmount *nfs_d_automount(struct path *path) | |||
| 136 | struct nfs_fh *fh = NULL; | 232 | struct nfs_fh *fh = NULL; |
| 137 | struct nfs_fattr *fattr = NULL; | 233 | struct nfs_fattr *fattr = NULL; |
| 138 | int err; | 234 | int err; |
| 235 | rpc_authflavor_t flavor = 1; | ||
| 139 | 236 | ||
| 140 | dprintk("--> nfs_d_automount()\n"); | 237 | dprintk("--> nfs_d_automount()\n"); |
| 141 | 238 | ||
| @@ -156,6 +253,13 @@ struct vfsmount *nfs_d_automount(struct path *path) | |||
| 156 | err = server->nfs_client->rpc_ops->lookup(server->client, parent->d_inode, | 253 | err = server->nfs_client->rpc_ops->lookup(server->client, parent->d_inode, |
| 157 | &path->dentry->d_name, | 254 | &path->dentry->d_name, |
| 158 | fh, fattr); | 255 | fh, fattr); |
| 256 | if (err == -EPERM) { | ||
| 257 | flavor = nfs_lookup_with_sec(server, parent, path->dentry, path, fh, fattr); | ||
| 258 | if (flavor < 0) | ||
| 259 | err = flavor; | ||
| 260 | else | ||
| 261 | err = 0; | ||
| 262 | } | ||
| 159 | dput(parent); | 263 | dput(parent); |
| 160 | if (err != 0) { | 264 | if (err != 0) { |
| 161 | mnt = ERR_PTR(err); | 265 | mnt = ERR_PTR(err); |
| @@ -165,7 +269,7 @@ struct vfsmount *nfs_d_automount(struct path *path) | |||
| 165 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) | 269 | if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) |
| 166 | mnt = nfs_do_refmount(path->dentry); | 270 | mnt = nfs_do_refmount(path->dentry); |
| 167 | else | 271 | else |
| 168 | mnt = nfs_do_submount(path->dentry, fh, fattr); | 272 | mnt = nfs_do_submount(path->dentry, fh, fattr, flavor); |
| 169 | if (IS_ERR(mnt)) | 273 | if (IS_ERR(mnt)) |
| 170 | goto out; | 274 | goto out; |
| 171 | 275 | ||
| @@ -232,17 +336,20 @@ static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server, | |||
| 232 | * @dentry - parent directory | 336 | * @dentry - parent directory |
| 233 | * @fh - filehandle for new root dentry | 337 | * @fh - filehandle for new root dentry |
| 234 | * @fattr - attributes for new root inode | 338 | * @fattr - attributes for new root inode |
| 339 | * @authflavor - security flavor to use when performing the mount | ||
| 235 | * | 340 | * |
| 236 | */ | 341 | */ |
| 237 | static struct vfsmount *nfs_do_submount(struct dentry *dentry, | 342 | static struct vfsmount *nfs_do_submount(struct dentry *dentry, |
| 238 | struct nfs_fh *fh, | 343 | struct nfs_fh *fh, |
| 239 | struct nfs_fattr *fattr) | 344 | struct nfs_fattr *fattr, |
| 345 | rpc_authflavor_t authflavor) | ||
| 240 | { | 346 | { |
| 241 | struct nfs_clone_mount mountdata = { | 347 | struct nfs_clone_mount mountdata = { |
| 242 | .sb = dentry->d_sb, | 348 | .sb = dentry->d_sb, |
| 243 | .dentry = dentry, | 349 | .dentry = dentry, |
| 244 | .fh = fh, | 350 | .fh = fh, |
| 245 | .fattr = fattr, | 351 | .fattr = fattr, |
| 352 | .authflavor = authflavor, | ||
| 246 | }; | 353 | }; |
| 247 | struct vfsmount *mnt = ERR_PTR(-ENOMEM); | 354 | struct vfsmount *mnt = ERR_PTR(-ENOMEM); |
| 248 | char *page = (char *) __get_free_page(GFP_USER); | 355 | char *page = (char *) __get_free_page(GFP_USER); |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 0b8bae11997..563463777d9 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -87,6 +87,8 @@ static int nfs4_map_errors(int err) | |||
| 87 | switch (err) { | 87 | switch (err) { |
| 88 | case -NFS4ERR_RESOURCE: | 88 | case -NFS4ERR_RESOURCE: |
| 89 | return -EREMOTEIO; | 89 | return -EREMOTEIO; |
| 90 | case -NFS4ERR_WRONGSEC: | ||
| 91 | return -EPERM; | ||
| 90 | case -NFS4ERR_BADOWNER: | 92 | case -NFS4ERR_BADOWNER: |
| 91 | case -NFS4ERR_BADNAME: | 93 | case -NFS4ERR_BADNAME: |
| 92 | return -EINVAL; | 94 | return -EINVAL; |
| @@ -2383,6 +2385,16 @@ static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, | |||
| 2383 | return status; | 2385 | return status; |
| 2384 | } | 2386 | } |
| 2385 | 2387 | ||
| 2388 | void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr, struct nfs_fh *fh) | ||
| 2389 | { | ||
| 2390 | memset(fh, 0, sizeof(struct nfs_fh)); | ||
| 2391 | fattr->fsid.major = 1; | ||
| 2392 | fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE | | ||
| 2393 | NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_FSID | NFS_ATTR_FATTR_MOUNTPOINT; | ||
| 2394 | fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO; | ||
| 2395 | fattr->nlink = 2; | ||
| 2396 | } | ||
| 2397 | |||
| 2386 | static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name, | 2398 | static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name, |
| 2387 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) | 2399 | struct nfs_fh *fhandle, struct nfs_fattr *fattr) |
| 2388 | { | 2400 | { |
| @@ -2392,6 +2404,8 @@ static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qst | |||
| 2392 | err = nfs4_handle_exception(NFS_SERVER(dir), | 2404 | err = nfs4_handle_exception(NFS_SERVER(dir), |
| 2393 | _nfs4_proc_lookup(clnt, dir, name, fhandle, fattr), | 2405 | _nfs4_proc_lookup(clnt, dir, name, fhandle, fattr), |
| 2394 | &exception); | 2406 | &exception); |
| 2407 | if (err == -EPERM) | ||
| 2408 | nfs_fixup_secinfo_attributes(fattr, fhandle); | ||
| 2395 | } while (exception.retry); | 2409 | } while (exception.retry); |
| 2396 | return err; | 2410 | return err; |
| 2397 | } | 2411 | } |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 98afcf947aa..21c3004b72d 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
| @@ -113,7 +113,7 @@ static int nfs4_stat_to_errno(int); | |||
| 113 | #define encode_restorefh_maxsz (op_encode_hdr_maxsz) | 113 | #define encode_restorefh_maxsz (op_encode_hdr_maxsz) |
| 114 | #define decode_restorefh_maxsz (op_decode_hdr_maxsz) | 114 | #define decode_restorefh_maxsz (op_decode_hdr_maxsz) |
| 115 | #define encode_fsinfo_maxsz (encode_getattr_maxsz) | 115 | #define encode_fsinfo_maxsz (encode_getattr_maxsz) |
| 116 | #define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 11) | 116 | #define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 15) |
| 117 | #define encode_renew_maxsz (op_encode_hdr_maxsz + 3) | 117 | #define encode_renew_maxsz (op_encode_hdr_maxsz + 3) |
| 118 | #define decode_renew_maxsz (op_decode_hdr_maxsz) | 118 | #define decode_renew_maxsz (op_decode_hdr_maxsz) |
| 119 | #define encode_setclientid_maxsz \ | 119 | #define encode_setclientid_maxsz \ |
| @@ -2966,6 +2966,7 @@ static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap) | |||
| 2966 | if (unlikely(!p)) | 2966 | if (unlikely(!p)) |
| 2967 | goto out_overflow; | 2967 | goto out_overflow; |
| 2968 | bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; | 2968 | bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; |
| 2969 | return -be32_to_cpup(p); | ||
| 2969 | } | 2970 | } |
| 2970 | return 0; | 2971 | return 0; |
| 2971 | out_overflow: | 2972 | out_overflow: |
| @@ -3953,6 +3954,10 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | |||
| 3953 | fattr->valid |= status; | 3954 | fattr->valid |= status; |
| 3954 | 3955 | ||
| 3955 | status = decode_attr_error(xdr, bitmap); | 3956 | status = decode_attr_error(xdr, bitmap); |
| 3957 | if (status == -NFS4ERR_WRONGSEC) { | ||
| 3958 | nfs_fixup_secinfo_attributes(fattr, fh); | ||
| 3959 | status = 0; | ||
| 3960 | } | ||
| 3956 | if (status < 0) | 3961 | if (status < 0) |
| 3957 | goto xdr_error; | 3962 | goto xdr_error; |
| 3958 | 3963 | ||
| @@ -6314,10 +6319,6 @@ static struct { | |||
| 6314 | { NFS4ERR_SYMLINK, -ELOOP }, | 6319 | { NFS4ERR_SYMLINK, -ELOOP }, |
| 6315 | { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP }, | 6320 | { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP }, |
| 6316 | { NFS4ERR_DEADLOCK, -EDEADLK }, | 6321 | { NFS4ERR_DEADLOCK, -EDEADLK }, |
| 6317 | { NFS4ERR_WRONGSEC, -EPERM }, /* FIXME: this needs | ||
| 6318 | * to be handled by a | ||
| 6319 | * middle-layer. | ||
| 6320 | */ | ||
| 6321 | { -1, -EIO } | 6322 | { -1, -EIO } |
| 6322 | }; | 6323 | }; |
| 6323 | 6324 | ||
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 3f32bf17584..fa1ba78ca2c 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
| @@ -82,6 +82,7 @@ struct nfs_fattr { | |||
| 82 | #define NFS_ATTR_FATTR_CHANGE (1U << 17) | 82 | #define NFS_ATTR_FATTR_CHANGE (1U << 17) |
| 83 | #define NFS_ATTR_FATTR_PRECHANGE (1U << 18) | 83 | #define NFS_ATTR_FATTR_PRECHANGE (1U << 18) |
| 84 | #define NFS_ATTR_FATTR_V4_REFERRAL (1U << 19) /* NFSv4 referral */ | 84 | #define NFS_ATTR_FATTR_V4_REFERRAL (1U << 19) /* NFSv4 referral */ |
| 85 | #define NFS_ATTR_FATTR_MOUNTPOINT (1U << 20) /* Treat as mountpoint */ | ||
| 85 | 86 | ||
| 86 | #define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \ | 87 | #define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \ |
| 87 | | NFS_ATTR_FATTR_MODE \ | 88 | | NFS_ATTR_FATTR_MODE \ |
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c index 8b4061049d7..6c844b01a1d 100644 --- a/net/sunrpc/auth_gss/gss_mech_switch.c +++ b/net/sunrpc/auth_gss/gss_mech_switch.c | |||
| @@ -160,6 +160,28 @@ gss_mech_get_by_name(const char *name) | |||
| 160 | 160 | ||
| 161 | EXPORT_SYMBOL_GPL(gss_mech_get_by_name); | 161 | EXPORT_SYMBOL_GPL(gss_mech_get_by_name); |
| 162 | 162 | ||
| 163 | struct gss_api_mech * | ||
| 164 | gss_mech_get_by_OID(struct xdr_netobj *obj) | ||
| 165 | { | ||
| 166 | struct gss_api_mech *pos, *gm = NULL; | ||
| 167 | |||
| 168 | spin_lock(®istered_mechs_lock); | ||
| 169 | list_for_each_entry(pos, ®istered_mechs, gm_list) { | ||
| 170 | if (obj->len == pos->gm_oid.len) { | ||
| 171 | if (0 == memcmp(obj->data, pos->gm_oid.data, obj->len)) { | ||
| 172 | if (try_module_get(pos->gm_owner)) | ||
| 173 | gm = pos; | ||
| 174 | break; | ||
| 175 | } | ||
| 176 | } | ||
| 177 | } | ||
| 178 | spin_unlock(®istered_mechs_lock); | ||
| 179 | return gm; | ||
| 180 | |||
| 181 | } | ||
| 182 | |||
| 183 | EXPORT_SYMBOL_GPL(gss_mech_get_by_OID); | ||
| 184 | |||
| 163 | static inline int | 185 | static inline int |
| 164 | mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor) | 186 | mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor) |
| 165 | { | 187 | { |
