Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
ecebe0fc
Commit
ecebe0fc
authored
Aug 23, 2004
by
Trond Myklebust
Browse files
Options
Browse Files
Download
Plain Diff
Merge
http://nfsclient.bkbits.net/linux-2.6
into fys.uio.no:/home/linux/bitkeeper/nfsclient-2.6
parents
f18badd1
e143b1c8
Changes
32
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
1253 additions
and
295 deletions
+1253
-295
fs/Kconfig
fs/Kconfig
+18
-2
fs/lockd/svclock.c
fs/lockd/svclock.c
+7
-2
fs/lockd/svcsubs.c
fs/lockd/svcsubs.c
+1
-1
fs/nfs/dir.c
fs/nfs/dir.c
+63
-58
fs/nfs/inode.c
fs/nfs/inode.c
+60
-94
fs/nfs/mount_clnt.c
fs/nfs/mount_clnt.c
+0
-2
fs/nfs/nfs2xdr.c
fs/nfs/nfs2xdr.c
+23
-4
fs/nfs/nfs3proc.c
fs/nfs/nfs3proc.c
+16
-8
fs/nfs/nfs3xdr.c
fs/nfs/nfs3xdr.c
+0
-4
fs/nfs/nfs4proc.c
fs/nfs/nfs4proc.c
+15
-11
fs/nfs/nfs4xdr.c
fs/nfs/nfs4xdr.c
+59
-37
fs/nfs/nfsroot.c
fs/nfs/nfsroot.c
+2
-4
fs/nfs/pagelist.c
fs/nfs/pagelist.c
+3
-12
fs/nfs/proc.c
fs/nfs/proc.c
+2
-0
fs/nfs/write.c
fs/nfs/write.c
+34
-31
include/linux/nfs.h
include/linux/nfs.h
+17
-0
include/linux/nfs4.h
include/linux/nfs4.h
+2
-0
include/linux/nfs_fs.h
include/linux/nfs_fs.h
+4
-4
include/linux/nfs_fs_sb.h
include/linux/nfs_fs_sb.h
+1
-0
include/linux/nfs_page.h
include/linux/nfs_page.h
+3
-5
include/linux/nfs_xdr.h
include/linux/nfs_xdr.h
+3
-1
include/linux/sunrpc/gss_asn1.h
include/linux/sunrpc/gss_asn1.h
+0
-1
include/linux/sunrpc/gss_spkm3.h
include/linux/sunrpc/gss_spkm3.h
+61
-0
net/sunrpc/auth_gss/Makefile
net/sunrpc/auth_gss/Makefile
+4
-0
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/auth_gss.c
+1
-1
net/sunrpc/auth_gss/gss_generic_token.c
net/sunrpc/auth_gss/gss_generic_token.c
+1
-1
net/sunrpc/auth_gss/gss_krb5_unseal.c
net/sunrpc/auth_gss/gss_krb5_unseal.c
+1
-1
net/sunrpc/auth_gss/gss_spkm3_mech.c
net/sunrpc/auth_gss/gss_spkm3_mech.c
+296
-0
net/sunrpc/auth_gss/gss_spkm3_seal.c
net/sunrpc/auth_gss/gss_spkm3_seal.c
+132
-0
net/sunrpc/auth_gss/gss_spkm3_token.c
net/sunrpc/auth_gss/gss_spkm3_token.c
+266
-0
net/sunrpc/auth_gss/gss_spkm3_unseal.c
net/sunrpc/auth_gss/gss_spkm3_unseal.c
+128
-0
net/sunrpc/clnt.c
net/sunrpc/clnt.c
+30
-11
No files found.
fs/Kconfig
View file @
ecebe0fc
...
...
@@ -1415,8 +1415,8 @@ config NFS_V3
bool "Provide NFSv3 client support"
depends on NFS_FS
help
Say Y here if you want your NFS client to be able to speak
the newer
version
3 of the NFS protocol.
Say Y here if you want your NFS client to be able to speak
version
3 of the NFS protocol.
If unsure, say Y.
...
...
@@ -1560,6 +1560,22 @@ config RPCSEC_GSS_KRB5
If unsure, say N.
config RPCSEC_GSS_SPKM3
tristate "Secure RPC: SPKM3 mechanism (EXPERIMENTAL)"
depends on SUNRPC && EXPERIMENTAL
select SUNRPC_GSS
select CRYPTO
select CRYPTO_MD5
select CRYPTO_DES
help
Provides for secure RPC calls by means of a gss-api
mechanism based on the SPKM3 public-key mechanism.
Note: Requires an auxiliary userspace daemon which may be found on
http://www.citi.umich.edu/projects/nfsv4/
If unsure, say N.
config SMB_FS
tristate "SMB file system support (to mount Windows shares etc.)"
depends on INET
...
...
fs/lockd/svclock.c
View file @
ecebe0fc
...
...
@@ -237,8 +237,13 @@ nlmsvc_delete_block(struct nlm_block *block, int unlock)
/* Remove block from list */
nlmsvc_remove_block
(
block
);
posix_unblock_lock
(
file
->
f_file
,
fl
);
block
->
b_granted
=
0
;
if
(
fl
->
fl_next
)
posix_unblock_lock
(
file
->
f_file
,
fl
);
if
(
unlock
)
{
fl
->
fl_type
=
F_UNLCK
;
posix_lock_file
(
file
->
f_file
,
fl
);
block
->
b_granted
=
0
;
}
/* If the block is in the middle of a GRANT callback,
* don't kill it yet. */
...
...
fs/lockd/svcsubs.c
View file @
ecebe0fc
...
...
@@ -67,7 +67,7 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
down
(
&
nlm_file_sema
);
for
(
file
=
nlm_files
[
hash
];
file
;
file
=
file
->
f_next
)
if
(
!
memcmp
(
&
file
->
f_handle
,
f
,
sizeof
(
*
f
)
))
if
(
!
nfs_compare_fh
(
&
file
->
f_handle
,
f
))
goto
found
;
dprintk
(
"lockd: creating file for (%08x %08x %08x %08x %08x %08x)
\n
"
,
...
...
fs/nfs/dir.c
View file @
ecebe0fc
...
...
@@ -610,7 +610,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
verifier
=
nfs_save_change_attribute
(
dir
);
error
=
nfs_cached_lookup
(
dir
,
dentry
,
&
fhandle
,
&
fattr
);
if
(
!
error
)
{
if
(
memcmp
(
NFS_FH
(
inode
),
&
fhandle
,
sizeof
(
struct
nfs_fh
))
!=
0
)
if
(
nfs_compare_fh
(
NFS_FH
(
inode
),
&
fhandle
)
)
goto
out_bad
;
if
(
nfs_lookup_verify_inode
(
inode
,
isopen
))
goto
out_zap_parent
;
...
...
@@ -623,7 +623,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
error
=
NFS_PROTO
(
dir
)
->
lookup
(
dir
,
&
dentry
->
d_name
,
&
fhandle
,
&
fattr
);
if
(
error
)
goto
out_bad
;
if
(
memcmp
(
NFS_FH
(
inode
),
&
fhandle
,
sizeof
(
struct
nfs_fh
))
!=
0
)
if
(
nfs_compare_fh
(
NFS_FH
(
inode
),
&
fhandle
)
)
goto
out_bad
;
if
((
error
=
nfs_refresh_inode
(
inode
,
&
fattr
))
!=
0
)
goto
out_bad
;
...
...
@@ -850,22 +850,22 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
unsigned
long
verifier
;
int
openflags
,
ret
=
0
;
/* NFS only supports OPEN for regular files */
if
(
inode
&&
!
S_ISREG
(
inode
->
i_mode
))
goto
no_open
;
parent
=
dget_parent
(
dentry
);
dir
=
parent
->
d_inode
;
if
(
!
is_atomic_open
(
dir
,
nd
))
goto
no_open
;
/* We can't create new files in nfs_open_revalidate(), so we
* optimize away revalidation of negative dentries.
*/
if
(
inode
==
NULL
)
goto
out
;
/* NFS only supports OPEN on regular files */
if
(
!
S_ISREG
(
inode
->
i_mode
))
goto
no_open
;
openflags
=
nd
->
intent
.
open
.
flags
;
if
(
openflags
&
O_CREAT
)
{
/* If this is a negative dentry, just drop it */
if
(
!
inode
)
goto
out
;
/* If this is exclusive open, just revalidate */
if
(
openflags
&
O_EXCL
)
goto
no_open
;
}
/* We cannot do exclusive creation on a positive dentry */
if
((
openflags
&
(
O_CREAT
|
O_EXCL
))
==
(
O_CREAT
|
O_EXCL
))
goto
no_open
;
/* We can't create new files, or truncate existing ones here */
openflags
&=
~
(
O_CREAT
|
O_TRUNC
);
...
...
@@ -1299,19 +1299,6 @@ nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
dfprintk
(
VFS
,
"NFS: symlink(%s/%ld, %s, %s)
\n
"
,
dir
->
i_sb
->
s_id
,
dir
->
i_ino
,
dentry
->
d_name
.
name
,
symname
);
error
=
-
ENAMETOOLONG
;
switch
(
NFS_PROTO
(
dir
)
->
version
)
{
case
2
:
if
(
strlen
(
symname
)
>
NFS2_MAXPATHLEN
)
goto
out
;
break
;
case
3
:
if
(
strlen
(
symname
)
>
NFS3_MAXPATHLEN
)
goto
out
;
default:
break
;
}
#ifdef NFS_PARANOIA
if
(
dentry
->
d_inode
)
printk
(
"nfs_proc_symlink: %s/%s not negative!
\n
"
,
...
...
@@ -1341,8 +1328,6 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
d_drop
(
dentry
);
}
unlock_kernel
();
out:
return
error
;
}
...
...
@@ -1498,10 +1483,56 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
return
error
;
}
int
nfs_permission
(
struct
inode
*
inode
,
int
mask
,
struct
nameidata
*
nd
)
static
int
nfs_access_get_cached
(
struct
inode
*
inode
,
struct
rpc_cred
*
cred
,
struct
nfs_access_entry
*
res
)
{
struct
nfs_access_entry
*
cache
=
&
NFS_I
(
inode
)
->
cache_access
;
if
(
cache
->
cred
!=
cred
||
time_after
(
jiffies
,
cache
->
jiffies
+
NFS_ATTRTIMEO
(
inode
))
||
(
NFS_FLAGS
(
inode
)
&
NFS_INO_INVALID_ATTR
))
return
-
ENOENT
;
memcpy
(
res
,
cache
,
sizeof
(
*
res
));
return
0
;
}
static
void
nfs_access_add_cache
(
struct
inode
*
inode
,
struct
nfs_access_entry
*
set
)
{
struct
nfs_access_entry
*
cache
=
&
NFS_I
(
inode
)
->
cache_access
;
if
(
cache
->
cred
!=
set
->
cred
)
{
if
(
cache
->
cred
)
put_rpccred
(
cache
->
cred
);
cache
->
cred
=
get_rpccred
(
set
->
cred
);
}
cache
->
jiffies
=
set
->
jiffies
;
cache
->
mask
=
set
->
mask
;
}
static
int
nfs_do_access
(
struct
inode
*
inode
,
struct
rpc_cred
*
cred
,
int
mask
)
{
struct
nfs_access_entry
cache
;
int
status
;
status
=
nfs_access_get_cached
(
inode
,
cred
,
&
cache
);
if
(
status
==
0
)
goto
out
;
/* Be clever: ask server to check for all possible rights */
cache
.
mask
=
MAY_EXEC
|
MAY_WRITE
|
MAY_READ
;
cache
.
cred
=
cred
;
cache
.
jiffies
=
jiffies
;
status
=
NFS_PROTO
(
inode
)
->
access
(
inode
,
&
cache
);
if
(
status
!=
0
)
return
status
;
nfs_access_add_cache
(
inode
,
&
cache
);
out:
if
((
cache
.
mask
&
mask
)
==
mask
)
return
0
;
return
-
EACCES
;
}
int
nfs_permission
(
struct
inode
*
inode
,
int
mask
,
struct
nameidata
*
nd
)
{
struct
nfs_access_cache
*
cache
=
&
NFS_I
(
inode
)
->
cache_access
;
struct
rpc_cred
*
cred
;
int
mode
=
inode
->
i_mode
;
int
res
;
...
...
@@ -1542,24 +1573,7 @@ nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
goto
out_notsup
;
cred
=
rpcauth_lookupcred
(
NFS_CLIENT
(
inode
)
->
cl_auth
,
0
);
if
(
cache
->
cred
==
cred
&&
time_before
(
jiffies
,
cache
->
jiffies
+
NFS_ATTRTIMEO
(
inode
))
&&
!
(
NFS_FLAGS
(
inode
)
&
NFS_INO_INVALID_ATTR
))
{
if
(
!
(
res
=
cache
->
err
))
{
/* Is the mask a subset of an accepted mask? */
if
((
cache
->
mask
&
mask
)
==
mask
)
goto
out
;
}
else
{
/* ...or is it a superset of a rejected mask? */
if
((
cache
->
mask
&
mask
)
==
cache
->
mask
)
goto
out
;
}
}
res
=
NFS_PROTO
(
inode
)
->
access
(
inode
,
cred
,
mask
);
if
(
!
res
||
res
==
-
EACCES
)
goto
add_cache
;
out:
res
=
nfs_do_access
(
inode
,
cred
,
mask
);
put_rpccred
(
cred
);
unlock_kernel
();
return
res
;
...
...
@@ -1568,15 +1582,6 @@ nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
res
=
vfs_permission
(
inode
,
mask
);
unlock_kernel
();
return
res
;
add_cache:
cache
->
jiffies
=
jiffies
;
if
(
cache
->
cred
)
put_rpccred
(
cache
->
cred
);
cache
->
cred
=
cred
;
cache
->
mask
=
mask
;
cache
->
err
=
res
;
unlock_kernel
();
return
res
;
}
/*
...
...
fs/nfs/inode.c
View file @
ecebe0fc
This diff is collapsed.
Click to expand it.
fs/nfs/mount_clnt.c
View file @
ecebe0fc
...
...
@@ -108,7 +108,6 @@ xdr_decode_fhstatus(struct rpc_rqst *req, u32 *p, struct mnt_fhstatus *res)
{
struct
nfs_fh
*
fh
=
res
->
fh
;
memset
((
void
*
)
fh
,
0
,
sizeof
(
*
fh
));
if
((
res
->
status
=
ntohl
(
*
p
++
))
==
0
)
{
fh
->
size
=
NFS2_FHSIZE
;
memcpy
(
fh
->
data
,
p
,
NFS2_FHSIZE
);
...
...
@@ -121,7 +120,6 @@ xdr_decode_fhstatus3(struct rpc_rqst *req, u32 *p, struct mnt_fhstatus *res)
{
struct
nfs_fh
*
fh
=
res
->
fh
;
memset
((
void
*
)
fh
,
0
,
sizeof
(
*
fh
));
if
((
res
->
status
=
ntohl
(
*
p
++
))
==
0
)
{
int
size
=
ntohl
(
*
p
++
);
if
(
size
<=
NFS3_FHSIZE
)
{
...
...
fs/nfs/nfs2xdr.c
View file @
ecebe0fc
...
...
@@ -77,8 +77,6 @@ xdr_encode_fhandle(u32 *p, struct nfs_fh *fhandle)
static
inline
u32
*
xdr_decode_fhandle
(
u32
*
p
,
struct
nfs_fh
*
fhandle
)
{
/* Zero handle first to allow comparisons */
memset
(
fhandle
,
0
,
sizeof
(
*
fhandle
));
/* NFSv2 handles have a fixed length */
fhandle
->
size
=
NFS2_FHSIZE
;
memcpy
(
fhandle
->
data
,
p
,
NFS2_FHSIZE
);
...
...
@@ -94,6 +92,23 @@ xdr_encode_time(u32 *p, struct timespec *timep)
return
p
;
}
static
inline
u32
*
xdr_encode_current_server_time
(
u32
*
p
,
struct
timespec
*
timep
)
{
/*
* Passing the invalid value useconds=1000000 is a
* Sun convention for "set to current server time".
* It's needed to make permissions checks for the
* "touch" program across v2 mounts to Solaris and
* Irix boxes work correctly. See description of
* sattr in section 6.1 of "NFS Illustrated" by
* Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5
*/
*
p
++
=
htonl
(
timep
->
tv_sec
);
*
p
++
=
htonl
(
1000000
);
return
p
;
}
static
inline
u32
*
xdr_decode_time
(
u32
*
p
,
struct
timespec
*
timep
)
{
...
...
@@ -142,15 +157,19 @@ xdr_encode_sattr(u32 *p, struct iattr *attr)
SATTR
(
p
,
attr
,
ATTR_GID
,
ia_gid
);
SATTR
(
p
,
attr
,
ATTR_SIZE
,
ia_size
);
if
(
attr
->
ia_valid
&
(
ATTR_ATIME
|
ATTR_ATIME_SET
)
)
{
if
(
attr
->
ia_valid
&
ATTR_ATIME_SET
)
{
p
=
xdr_encode_time
(
p
,
&
attr
->
ia_atime
);
}
else
if
(
attr
->
ia_valid
&
ATTR_ATIME
)
{
p
=
xdr_encode_current_server_time
(
p
,
&
attr
->
ia_atime
);
}
else
{
*
p
++
=
~
(
u32
)
0
;
*
p
++
=
~
(
u32
)
0
;
}
if
(
attr
->
ia_valid
&
(
ATTR_MTIME
|
ATTR_MTIME_SET
)
)
{
if
(
attr
->
ia_valid
&
ATTR_MTIME_SET
)
{
p
=
xdr_encode_time
(
p
,
&
attr
->
ia_mtime
);
}
else
if
(
attr
->
ia_valid
&
ATTR_MTIME
)
{
p
=
xdr_encode_current_server_time
(
p
,
&
attr
->
ia_mtime
);
}
else
{
*
p
++
=
~
(
u32
)
0
;
*
p
++
=
~
(
u32
)
0
;
...
...
fs/nfs/nfs3proc.c
View file @
ecebe0fc
...
...
@@ -164,8 +164,7 @@ nfs3_proc_lookup(struct inode *dir, struct qstr *name,
return
status
;
}
static
int
nfs3_proc_access
(
struct
inode
*
inode
,
struct
rpc_cred
*
cred
,
int
mode
)
static
int
nfs3_proc_access
(
struct
inode
*
inode
,
struct
nfs_access_entry
*
entry
)
{
struct
nfs_fattr
fattr
;
struct
nfs3_accessargs
arg
=
{
...
...
@@ -178,9 +177,10 @@ nfs3_proc_access(struct inode *inode, struct rpc_cred *cred, int mode)
.
rpc_proc
=
&
nfs3_procedures
[
NFS3PROC_ACCESS
],
.
rpc_argp
=
&
arg
,
.
rpc_resp
=
&
res
,
.
rpc_cred
=
cred
.
rpc_cred
=
entry
->
cred
};
int
status
;
int
mode
=
entry
->
mask
;
int
status
;
dprintk
(
"NFS call access
\n
"
);
fattr
.
valid
=
0
;
...
...
@@ -200,10 +200,16 @@ nfs3_proc_access(struct inode *inode, struct rpc_cred *cred, int mode)
}
status
=
rpc_call_sync
(
NFS_CLIENT
(
inode
),
&
msg
,
0
);
nfs_refresh_inode
(
inode
,
&
fattr
);
dprintk
(
"NFS reply access
\n
"
);
if
(
status
==
0
&&
(
arg
.
access
&
res
.
access
)
!=
arg
.
access
)
status
=
-
EACCES
;
if
(
status
==
0
)
{
entry
->
mask
=
0
;
if
(
res
.
access
&
NFS3_ACCESS_READ
)
entry
->
mask
|=
MAY_READ
;
if
(
res
.
access
&
(
NFS3_ACCESS_MODIFY
|
NFS3_ACCESS_EXTEND
|
NFS3_ACCESS_DELETE
))
entry
->
mask
|=
MAY_WRITE
;
if
(
res
.
access
&
(
NFS3_ACCESS_LOOKUP
|
NFS3_ACCESS_EXECUTE
))
entry
->
mask
|=
MAY_EXEC
;
}
dprintk
(
"NFS reply access, status = %d
\n
"
,
status
);
return
status
;
}
...
...
@@ -534,6 +540,8 @@ nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
};
int
status
;
if
(
path
->
len
>
NFS3_MAXPATHLEN
)
return
-
ENAMETOOLONG
;
dprintk
(
"NFS call symlink %s -> %s
\n
"
,
name
->
name
,
path
->
name
);
dir_attr
.
valid
=
0
;
fattr
->
valid
=
0
;
...
...
fs/nfs/nfs3xdr.c
View file @
ecebe0fc
...
...
@@ -109,10 +109,6 @@ xdr_encode_fhandle(u32 *p, struct nfs_fh *fh)
static
inline
u32
*
xdr_decode_fhandle
(
u32
*
p
,
struct
nfs_fh
*
fh
)
{
/*
* Zero all nonused bytes
*/
memset
((
u8
*
)
fh
,
0
,
sizeof
(
*
fh
));
if
((
fh
->
size
=
ntohl
(
*
p
++
))
<=
NFS3_FHSIZE
)
{
memcpy
(
fh
->
data
,
p
,
fh
->
size
);
return
p
+
XDR_QUADLEN
(
fh
->
size
);
...
...
fs/nfs/nfs4proc.c
View file @
ecebe0fc
...
...
@@ -734,9 +734,8 @@ static int nfs4_proc_lookup(struct inode *dir, struct qstr *name,
return
nfs4_map_errors
(
status
);
}
static
int
nfs4_proc_access
(
struct
inode
*
inode
,
struct
rpc_cred
*
cred
,
int
mode
)
static
int
nfs4_proc_access
(
struct
inode
*
inode
,
struct
nfs_access_entry
*
entry
)
{
int
status
;
struct
nfs4_accessargs
args
=
{
.
fh
=
NFS_FH
(
inode
),
};
...
...
@@ -745,8 +744,10 @@ static int nfs4_proc_access(struct inode *inode, struct rpc_cred *cred, int mode
.
rpc_proc
=
&
nfs4_procedures
[
NFSPROC4_CLNT_ACCESS
],
.
rpc_argp
=
&
args
,
.
rpc_resp
=
&
res
,
.
rpc_cred
=
cred
,
.
rpc_cred
=
entry
->
cred
,
};
int
mode
=
entry
->
mask
;
int
status
;
/*
* Determine which access bits we want to ask for...
...
...
@@ -758,8 +759,7 @@ static int nfs4_proc_access(struct inode *inode, struct rpc_cred *cred, int mode
args
.
access
|=
NFS4_ACCESS_MODIFY
|
NFS4_ACCESS_EXTEND
|
NFS4_ACCESS_DELETE
;
if
(
mode
&
MAY_EXEC
)
args
.
access
|=
NFS4_ACCESS_LOOKUP
;
}
else
{
}
else
{
if
(
mode
&
MAY_WRITE
)
args
.
access
|=
NFS4_ACCESS_MODIFY
|
NFS4_ACCESS_EXTEND
;
if
(
mode
&
MAY_EXEC
)
...
...
@@ -767,11 +767,13 @@ static int nfs4_proc_access(struct inode *inode, struct rpc_cred *cred, int mode
}
status
=
rpc_call_sync
(
NFS_CLIENT
(
inode
),
&
msg
,
0
);
if
(
!
status
)
{
if
(
args
.
access
!=
res
.
supported
)
{
printk
(
KERN_NOTICE
"NFS: server didn't support all access bits!
\n
"
);
status
=
-
ENOTSUPP
;
}
else
if
((
args
.
access
&
res
.
access
)
!=
args
.
access
)
status
=
-
EACCES
;
entry
->
mask
=
0
;
if
(
res
.
access
&
NFS4_ACCESS_READ
)
entry
->
mask
|=
MAY_READ
;
if
(
res
.
access
&
(
NFS4_ACCESS_MODIFY
|
NFS4_ACCESS_EXTEND
|
NFS4_ACCESS_DELETE
))
entry
->
mask
|=
MAY_WRITE
;
if
(
res
.
access
&
(
NFS4_ACCESS_LOOKUP
|
NFS4_ACCESS_EXECUTE
))
entry
->
mask
|=
MAY_EXEC
;
}
return
nfs4_map_errors
(
status
);
}
...
...
@@ -1090,12 +1092,14 @@ static int nfs4_proc_symlink(struct inode *dir, struct qstr *name,
.
fattr
=
fattr
,
};
struct
rpc_message
msg
=
{
.
rpc_proc
=
&
nfs4_procedures
[
NFSPROC4_CLNT_
CREATE
],
.
rpc_proc
=
&
nfs4_procedures
[
NFSPROC4_CLNT_
SYMLINK
],
.
rpc_argp
=
&
arg
,
.
rpc_resp
=
&
res
,
};
int
status
;
if
(
path
->
len
>
NFS4_MAXPATHLEN
)
return
-
ENAMETOOLONG
;
arg
.
u
.
symlink
=
path
;
fattr
->
valid
=
0
;
...
...
fs/nfs/nfs4xdr.c
View file @
ecebe0fc
...
...
@@ -84,6 +84,7 @@ static int nfs_stat_to_errno(int);
((3+NFS4_FHSIZE) >> 2))
#define encode_getattr_maxsz (op_encode_hdr_maxsz + 3)
#define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2))
#define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2))
#define nfs4_fattr_bitmap_maxsz (36 + 2 * nfs4_name_maxsz)
#define decode_getattr_maxsz (op_decode_hdr_maxsz + 3 + \
nfs4_fattr_bitmap_maxsz)
...
...
@@ -118,8 +119,13 @@ static int nfs_stat_to_errno(int);
#define encode_link_maxsz (op_encode_hdr_maxsz + \
nfs4_name_maxsz)
#define decode_link_maxsz (op_decode_hdr_maxsz + 5)
#define encode_symlink_maxsz (op_encode_hdr_maxsz + \
1 + nfs4_name_maxsz + \
nfs4_path_maxsz + \
nfs4_fattr_bitmap_maxsz)
#define decode_symlink_maxsz (op_decode_hdr_maxsz + 8)
#define encode_create_maxsz (op_encode_hdr_maxsz + \
2 +
2 *
nfs4_name_maxsz + \
2 + nfs4_name_maxsz + \
nfs4_fattr_bitmap_maxsz)
#define decode_create_maxsz (op_decode_hdr_maxsz + 8)
#define NFS4_enc_compound_sz (1024)
/* XXX: large enough? */
...
...
@@ -313,6 +319,16 @@ static int nfs_stat_to_errno(int);
decode_savefh_maxsz + \
decode_putfh_maxsz + \
decode_link_maxsz)
#define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_symlink_maxsz + \
encode_getattr_maxsz + \
encode_getfh_maxsz)
#define NFS4_dec_symlink_sz (compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
decode_symlink_maxsz + \
decode_getattr_maxsz + \
decode_getfh_maxsz)
#define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
encode_create_maxsz + \
...
...
@@ -927,7 +943,7 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
WRITE32
(
OP_READDIR
);
WRITE64
(
readdir
->
cookie
);
WRITEMEM
(
readdir
->
verifier
.
data
,
sizeof
(
readdir
->
verifier
.
data
));
WRITE32
(
readdir
->
count
>>
5
);
/* meaningless "dircount" field
*/
WRITE32
(
readdir
->
count
>>
1
);
/* We're not doing readdirplus
*/
WRITE32
(
readdir
->
count
);
WRITE32
(
2
);
WRITE32
(
FATTR4_WORD0_FILEID
);
...
...
@@ -1243,6 +1259,14 @@ static int nfs4_xdr_enc_create(struct rpc_rqst *req, uint32_t *p, const struct n
return
status
;
}
/*
* Encode SYMLINK request
*/
static
int
nfs4_xdr_enc_symlink
(
struct
rpc_rqst
*
req
,
uint32_t
*
p
,
const
struct
nfs4_create_arg
*
args
)
{
return
nfs4_xdr_enc_create
(
req
,
p
,
args
);
}
/*
* Encode GETATTR request
*/
...
...
@@ -2817,8 +2841,8 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
struct
kvec
*
iov
=
rcvbuf
->
head
;
unsigned
int
nr
,
pglen
=
rcvbuf
->
page_len
;
uint32_t
*
end
,
*
entry
,
*
p
,
*
kaddr
;
uint32_t
len
,
attrlen
,
word
;
int
i
,
hdrlen
,
recvd
,
status
;
uint32_t
len
,
attrlen
;
int
hdrlen
,
recvd
,
status
;
status
=
decode_op_hdr
(
xdr
,
OP_READDIR
);
if
(
status
)
...
...
@@ -2839,42 +2863,24 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
for
(
nr
=
0
;
*
p
++
;
nr
++
)
{
if
(
p
+
3
>
end
)
goto
short_pkt
;
p
+=
2
;
/* cookie */
len
=
ntohl
(
*
p
++
);
/* filename length */
p
+=
2
;
/* cookie */
len
=
ntohl
(
*
p
++
);
/* filename length */
if
(
len
>
NFS4_MAXNAMLEN
)
{
printk
(
KERN_WARNING
"NFS: giant filename in readdir (len 0x%x)
\n
"
,
len
);
goto
err_unmap
;
}
p
+=
XDR_QUADLEN
(
len
);
if
(
p
+
1
>
end
)
goto
short_pkt
;
len
=
ntohl
(
*
p
++
);
/* bitmap length */
if
(
len
>
10
)
{
printk
(
KERN_WARNING
"NFS: giant bitmap in readdir (len 0x%x)
\n
"
,
len
);
goto
err_unmap
;
}
if
(
p
+
len
+
1
>
end
)
goto
short_pkt
;
attrlen
=
0
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
word
=
ntohl
(
*
p
++
);
if
(
!
word
)
continue
;
else
if
(
i
==
0
&&
word
==
FATTR4_WORD0_FILEID
)
{
attrlen
=
8
;
continue
;
}
printk
(
KERN_WARNING
"NFS: unexpected bitmap word in readdir (0x%x)
\n
"
,
word
);
goto
err_unmap
;
}
if
(
ntohl
(
*
p
++
)
!=
attrlen
)
{
printk
(
KERN_WARNING
"NFS: unexpected attrlen in readdir
\n
"
);
goto
err_unmap
;
}
p
+=
XDR_QUADLEN
(
attrlen
);
len
=
ntohl
(
*
p
++
);
/* bitmap length */
p
+=
len
;
if
(
p
+
1
>
end
)
goto
short_pkt
;
attrlen
=
XDR_QUADLEN
(
ntohl
(
*
p
++
));
p
+=
attrlen
;
/* attributes */
if
(
p
+
2
>
end
)
goto
short_pkt
;
entry
=
p
;
}
if
(
!
nr
&&
(
entry
[
0
]
!=
0
||
entry
[
1
]
==
0
))
goto
short_pkt
;
...
...
@@ -3221,6 +3227,14 @@ static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_
return
status
;
}
/*
* Decode SYMLINK response
*/
static
int
nfs4_xdr_dec_symlink
(
struct
rpc_rqst
*
rqstp
,
uint32_t
*
p
,
struct
nfs4_create_res
*
res
)
{
return
nfs4_xdr_dec_create
(
rqstp
,
p
,
res
);
}
/*
* Decode GETATTR response
*/
...
...
@@ -3667,6 +3681,7 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, s
uint32_t
*
nfs4_decode_dirent
(
uint32_t
*
p
,
struct
nfs_entry
*
entry
,
int
plus
)
{
uint32_t
bitmap
[
1
]
=
{
0
};
uint32_t
len
;
if
(
!*
p
++
)
{
...
...
@@ -3689,11 +3704,17 @@ uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus)
*/
entry
->
ino
=
1
;
len
=
ntohl
(
*
p
++
);
/* bitmap length */
p
+=
len
;
len
=
ntohl
(
*
p
++
);
/* attribute buffer length */
if
(
len
)
p
=
xdr_decode_hyper
(
p
,
&
entry
->
ino
);
len
=
ntohl
(
*
p
++
);
/* bitmap length */
if
(
len
>
0
)
{
bitmap
[
0
]
=
ntohl
(
*
p
);
p
+=
len
;
}
len
=
XDR_QUADLEN
(
ntohl
(
*
p
++
));
/* attribute buffer length */
if
(
len
>
0
)
{
if
(
bitmap
[
0
]
==
FATTR4_WORD0_FILEID
)
xdr_decode_hyper
(
p
,
&
entry
->
ino
);
p
+=
len
;
}
entry
->
eof
=
!
p
[
0
]
&&
p
[
1
];
return
p
;
...
...
@@ -3756,7 +3777,7 @@ nfs_stat_to_errno(int stat)
if
(
nfs_errtbl
[
i
].
stat
==
stat
)
return
nfs_errtbl
[
i
].
errno
;
}
if
(
stat
<
0
)
{
if
(
stat
<
=
10000
||
stat
>
1010
0
)
{
/* The server is looney tunes. */
return
ESERVERFAULT
;
}
...
...
@@ -3804,6 +3825,7 @@ struct rpc_procinfo nfs4_procedures[] = {
PROC
(
REMOVE
,
enc_remove
,
dec_remove
),
PROC
(
RENAME
,
enc_rename
,
dec_rename
),
PROC
(
LINK
,
enc_link
,
dec_link
),
PROC
(
SYMLINK
,
enc_symlink
,
dec_symlink
),
PROC
(
CREATE
,
enc_create
,
dec_create
),
PROC
(
PATHCONF
,
enc_pathconf
,
dec_pathconf
),
PROC
(
STATFS
,
enc_statfs
,
dec_statfs
),
...
...
fs/nfs/nfsroot.c
View file @
ecebe0fc
...
...
@@ -495,10 +495,8 @@ static int __init root_nfs_get_handle(void)
if
(
status
<
0
)
printk
(
KERN_ERR
"Root-NFS: Server returned error %d "
"while mounting %s
\n
"
,
status
,
nfs_path
);
else
{
nfs_data
.
root
.
size
=
fh
.
size
;
memcpy
(
nfs_data
.
root
.
data
,
fh
.
data
,
fh
.
size
);
}
else
nfs_copy_fh
(
nfs_data
.
root
,
fh
);
return
status
;
}
...
...
fs/nfs/pagelist.c
View file @
ecebe0fc
...
...
@@ -21,11 +21,6 @@
#define NFS_PARANOIA 1
/*
* Spinlock
*/
spinlock_t
nfs_wreq_lock
=
SPIN_LOCK_UNLOCKED
;
static
kmem_cache_t
*
nfs_page_cachep
;
static
inline
struct
nfs_page
*
...
...
@@ -95,7 +90,7 @@ nfs_create_request(struct file *file, struct inode *inode,
req
->
wb_pgbase
=
offset
;
req
->
wb_bytes
=
count
;
req
->
wb_inode
=
inode
;
req
->
wb_count
=
1
;
atomic_set
(
&
req
->
wb_count
,
1
)
;
server
->
rpc_ops
->
request_init
(
req
,
file
);
return
req
;
...
...
@@ -137,12 +132,8 @@ void nfs_clear_request(struct nfs_page *req)
void
nfs_release_request
(
struct
nfs_page
*
req
)
{
spin_lock
(
&
nfs_wreq_lock
);
if
(
--
req
->
wb_count
)
{
spin_unlock
(
&
nfs_wreq_lock
);
if
(
!
atomic_dec_and_test
(
&
req
->
wb_count
))
return
;
}
spin_unlock
(
&
nfs_wreq_lock
);
#ifdef NFS_PARANOIA
BUG_ON
(
!
list_empty
(
&
req
->
wb_list
));
...
...
@@ -254,7 +245,7 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
* If the number of requests is set to 0, the entire address_space
* starting at index idx_start, is scanned.
* The requests are *not* checked to ensure that they form a contiguous set.
* You must be holding the
nfs_w
req_lock when calling this function
* You must be holding the
inode's
req_lock when calling this function
*/
int
nfs_scan_list
(
struct
list_head
*
head
,
struct
list_head
*
dst
,
...
...
fs/nfs/proc.c
View file @
ecebe0fc
...
...
@@ -400,6 +400,8 @@ nfs_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
};
int
status
;
if
(
path
->
len
>
NFS2_MAXPATHLEN
)
return
-
ENAMETOOLONG
;
dprintk
(
"NFS call symlink %s -> %s
\n
"
,
name
->
name
,
path
->
name
);
fattr
->
valid
=
0
;
status
=
rpc_call
(
NFS_CLIENT
(
dir
),
NFSPROC_SYMLINK
,
&
arg
,
NULL
,
0
);
...
...
fs/nfs/write.c
View file @
ecebe0fc
...
...
@@ -389,7 +389,7 @@ nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
nfs_begin_data_update
(
inode
);
}
nfsi
->
npages
++
;
req
->
wb_count
++
;
atomic_inc
(
&
req
->
wb_count
)
;
return
0
;
}
...
...
@@ -399,21 +399,20 @@ nfs_inode_add_request(struct inode *inode, struct nfs_page *req)
static
void
nfs_inode_remove_request
(
struct
nfs_page
*
req
)
{
struct
nfs_inode
*
nfsi
;
struct
inode
*
inode
;
struct
inode
*
inode
=
req
->
wb_inode
;
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
)
;
BUG_ON
(
!
NFS_WBACK_BUSY
(
req
));
spin_lock
(
&
nfs_wreq_lock
);
inode
=
req
->
wb_inode
;
nfsi
=
NFS_I
(
inode
);
spin_lock
(
&
nfsi
->
req_lock
);
radix_tree_delete
(
&
nfsi
->
nfs_page_tree
,
req
->
wb_index
);
nfsi
->
npages
--
;
if
(
!
nfsi
->
npages
)
{
spin_unlock
(
&
nfs
_w
req_lock
);
spin_unlock
(
&
nfs
i
->
req_lock
);
nfs_end_data_update_defer
(
inode
);
iput
(
inode
);
}
else
spin_unlock
(
&
nfs
_w
req_lock
);
spin_unlock
(
&
nfs
i
->
req_lock
);
nfs_clear_request
(
req
);
nfs_release_request
(
req
);
}
...
...
@@ -429,7 +428,7 @@ _nfs_find_request(struct inode *inode, unsigned long index)
req
=
(
struct
nfs_page
*
)
radix_tree_lookup
(
&
nfsi
->
nfs_page_tree
,
index
);
if
(
req
)
req
->
wb_count
++
;
atomic_inc
(
&
req
->
wb_count
)
;
return
req
;
}
...
...
@@ -437,10 +436,11 @@ static struct nfs_page *
nfs_find_request
(
struct
inode
*
inode
,
unsigned
long
index
)
{
struct
nfs_page
*
req
;
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
spin_lock
(
&
nfs
_w
req_lock
);
spin_lock
(
&
nfs
i
->
req_lock
);
req
=
_nfs_find_request
(
inode
,
index
);
spin_unlock
(
&
nfs
_w
req_lock
);
spin_unlock
(
&
nfs
i
->
req_lock
);
return
req
;
}
...
...
@@ -453,10 +453,10 @@ nfs_mark_request_dirty(struct nfs_page *req)
struct
inode
*
inode
=
req
->
wb_inode
;
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
spin_lock
(
&
nfs
_w
req_lock
);
spin_lock
(
&
nfs
i
->
req_lock
);
nfs_list_add_request
(
req
,
&
nfsi
->
dirty
);
nfsi
->
ndirty
++
;
spin_unlock
(
&
nfs
_w
req_lock
);
spin_unlock
(
&
nfs
i
->
req_lock
);
inc_page_state
(
nr_dirty
);
mark_inode_dirty
(
inode
);
}
...
...
@@ -481,10 +481,10 @@ nfs_mark_request_commit(struct nfs_page *req)
struct
inode
*
inode
=
req
->
wb_inode
;
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
spin_lock
(
&
nfs
_w
req_lock
);
spin_lock
(
&
nfs
i
->
req_lock
);
nfs_list_add_request
(
req
,
&
nfsi
->
commit
);
nfsi
->
ncommit
++
;
spin_unlock
(
&
nfs
_w
req_lock
);
spin_unlock
(
&
nfs
i
->
req_lock
);
inc_page_state
(
nr_unstable
);
mark_inode_dirty
(
inode
);
}
...
...
@@ -509,7 +509,7 @@ nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int
else
idx_end
=
idx_start
+
npages
-
1
;
spin_lock
(
&
nfs
_w
req_lock
);
spin_lock
(
&
nfs
i
->
req_lock
);
next
=
idx_start
;
while
(
radix_tree_gang_lookup
(
&
nfsi
->
nfs_page_tree
,
(
void
**
)
&
req
,
next
,
1
))
{
if
(
req
->
wb_index
>
idx_end
)
...
...
@@ -519,16 +519,16 @@ nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int
if
(
!
NFS_WBACK_BUSY
(
req
))
continue
;
req
->
wb_count
++
;
spin_unlock
(
&
nfs
_w
req_lock
);
atomic_inc
(
&
req
->
wb_count
)
;
spin_unlock
(
&
nfs
i
->
req_lock
);
error
=
nfs_wait_on_request
(
req
);
nfs_release_request
(
req
);
if
(
error
<
0
)
return
error
;
spin_lock
(
&
nfs
_w
req_lock
);
spin_lock
(
&
nfs
i
->
req_lock
);
res
++
;
}
spin_unlock
(
&
nfs
_w
req_lock
);
spin_unlock
(
&
nfs
i
->
req_lock
);
return
res
;
}
...
...
@@ -624,6 +624,7 @@ nfs_update_request(struct file* file, struct inode *inode, struct page *page,
unsigned
int
offset
,
unsigned
int
bytes
)
{
struct
nfs_server
*
server
=
NFS_SERVER
(
inode
);
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
struct
nfs_page
*
req
,
*
new
=
NULL
;
unsigned
long
rqend
,
end
;
...
...
@@ -635,19 +636,19 @@ nfs_update_request(struct file* file, struct inode *inode, struct page *page,
/* Loop over all inode entries and see if we find
* A request for the page we wish to update
*/
spin_lock
(
&
nfs
_w
req_lock
);
spin_lock
(
&
nfs
i
->
req_lock
);
req
=
_nfs_find_request
(
inode
,
page
->
index
);
if
(
req
)
{
if
(
!
nfs_lock_request_dontget
(
req
))
{
int
error
;
spin_unlock
(
&
nfs
_w
req_lock
);
spin_unlock
(
&
nfs
i
->
req_lock
);
error
=
nfs_wait_on_request
(
req
);
nfs_release_request
(
req
);
if
(
error
<
0
)
return
ERR_PTR
(
error
);
continue
;
}
spin_unlock
(
&
nfs
_w
req_lock
);
spin_unlock
(
&
nfs
i
->
req_lock
);
if
(
new
)
nfs_release_request
(
new
);
break
;
...
...
@@ -658,15 +659,15 @@ nfs_update_request(struct file* file, struct inode *inode, struct page *page,
nfs_lock_request_dontget
(
new
);
error
=
nfs_inode_add_request
(
inode
,
new
);
if
(
error
)
{
spin_unlock
(
&
nfs
_w
req_lock
);
spin_unlock
(
&
nfs
i
->
req_lock
);
nfs_unlock_request
(
new
);
return
ERR_PTR
(
error
);
}
spin_unlock
(
&
nfs
_w
req_lock
);
spin_unlock
(
&
nfs
i
->
req_lock
);
nfs_mark_request_dirty
(
new
);
return
new
;
}
spin_unlock
(
&
nfs
_w
req_lock
);
spin_unlock
(
&
nfs
i
->
req_lock
);
new
=
nfs_create_request
(
file
,
inode
,
page
,
offset
,
bytes
);
if
(
IS_ERR
(
new
))
...
...
@@ -1347,13 +1348,14 @@ nfs_commit_done(struct rpc_task *task)
int
nfs_flush_inode
(
struct
inode
*
inode
,
unsigned
long
idx_start
,
unsigned
int
npages
,
int
how
)
{
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
LIST_HEAD
(
head
);
int
res
,
error
=
0
;
spin_lock
(
&
nfs
_w
req_lock
);
spin_lock
(
&
nfs
i
->
req_lock
);
res
=
nfs_scan_dirty
(
inode
,
&
head
,
idx_start
,
npages
);
spin_unlock
(
&
nfs
_w
req_lock
);
spin_unlock
(
&
nfs
i
->
req_lock
);
if
(
res
)
error
=
nfs_flush_list
(
&
head
,
NFS_SERVER
(
inode
)
->
wpages
,
how
);
if
(
error
<
0
)
...
...
@@ -1365,18 +1367,19 @@ int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
int
nfs_commit_inode
(
struct
inode
*
inode
,
unsigned
long
idx_start
,
unsigned
int
npages
,
int
how
)
{
struct
nfs_inode
*
nfsi
=
NFS_I
(
inode
);
LIST_HEAD
(
head
);
int
res
,
error
=
0
;
spin_lock
(
&
nfs
_w
req_lock
);
spin_lock
(
&
nfs
i
->
req_lock
);
res
=
nfs_scan_commit
(
inode
,
&
head
,
idx_start
,
npages
);
if
(
res
)
{
res
+=
nfs_scan_commit
(
inode
,
&
head
,
0
,
0
);
spin_unlock
(
&
nfs
_w
req_lock
);
spin_unlock
(
&
nfs
i
->
req_lock
);
error
=
nfs_commit_list
(
&
head
,
how
);
}
else
spin_unlock
(
&
nfs
_w
req_lock
);
spin_unlock
(
&
nfs
i
->
req_lock
);
if
(
error
<
0
)
return
error
;
return
res
;
...
...
include/linux/nfs.h
View file @
ecebe0fc
...
...
@@ -8,6 +8,7 @@
#define _LINUX_NFS_H
#include <linux/sunrpc/msg_prot.h>
#include <linux/string.h>
#define NFS_PROGRAM 100003
#define NFS_PORT 2049
...
...
@@ -138,6 +139,22 @@ struct nfs_fh {
unsigned
char
data
[
NFS_MAXFHSIZE
];
};
/*
* Returns a zero iff the size and data fields match.
* Checks only "size" bytes in the data field.
*/
static
inline
int
nfs_compare_fh
(
const
struct
nfs_fh
*
a
,
const
struct
nfs_fh
*
b
)
{
return
a
->
size
!=
b
->
size
||
memcmp
(
a
->
data
,
b
->
data
,
a
->
size
)
!=
0
;
}
static
inline
void
nfs_copy_fh
(
struct
nfs_fh
*
target
,
const
struct
nfs_fh
*
source
)
{
target
->
size
=
source
->
size
;
memcpy
(
target
->
data
,
source
->
data
,
source
->
size
);
}
/*
* This is really a general kernel constant, but since nothing like
* this is defined in the kernel headers, I have to do it here.
...
...
include/linux/nfs4.h
View file @
ecebe0fc
...
...
@@ -18,6 +18,7 @@
#define NFS4_VERIFIER_SIZE 8
#define NFS4_FHSIZE 128
#define NFS4_MAXPATHLEN PATH_MAX
#define NFS4_MAXNAMLEN NAME_MAX
#define NFS4_ACCESS_READ 0x0001
...
...
@@ -372,6 +373,7 @@ enum {
NFSPROC4_CLNT_REMOVE
,
NFSPROC4_CLNT_RENAME
,
NFSPROC4_CLNT_LINK
,
NFSPROC4_CLNT_SYMLINK
,
NFSPROC4_CLNT_CREATE
,
NFSPROC4_CLNT_PATHCONF
,
NFSPROC4_CLNT_STATFS
,
...
...
include/linux/nfs_fs.h
View file @
ecebe0fc
...
...
@@ -75,13 +75,12 @@
#ifdef __KERNEL__
/*
* NFSv3
Access mode cache
* NFSv3
/v4 Access mode cache entry
*/
struct
nfs_access_
cache
{
struct
nfs_access_
entry
{
unsigned
long
jiffies
;
struct
rpc_cred
*
cred
;
int
mask
;
int
err
;
};
/*
...
...
@@ -137,7 +136,7 @@ struct nfs_inode {
*/
atomic_t
data_updates
;
struct
nfs_access_
cache
cache_access
;
struct
nfs_access_
entry
cache_access
;
/*
* This is the cookie verifier used for NFSv3 readdir
...
...
@@ -148,6 +147,7 @@ struct nfs_inode {
/*
* This is the list of dirty unwritten pages.
*/
spinlock_t
req_lock
;
struct
list_head
dirty
;
struct
list_head
commit
;
struct
radix_tree_root
nfs_page_tree
;
...
...
include/linux/nfs_fs_sb.h
View file @
ecebe0fc
...
...
@@ -18,6 +18,7 @@ struct nfs_server {
unsigned
int
rpages
;
/* read size (in pages) */
unsigned
int
wsize
;
/* write size */
unsigned
int
wpages
;
/* write size (in pages) */
unsigned
int
wtmult
;
/* server disk block size */
unsigned
int
dtsize
;
/* readdir size */
unsigned
int
bsize
;
/* server block size */
unsigned
int
acregmin
;
/* attr cache timeouts */
...
...
include/linux/nfs_page.h
View file @
ecebe0fc
...
...
@@ -40,8 +40,8 @@ struct nfs_page {
unsigned
long
wb_index
;
/* Offset >> PAGE_CACHE_SHIFT */
unsigned
int
wb_offset
,
/* Offset & ~PAGE_CACHE_MASK */
wb_pgbase
,
/* Start of page data */
wb_bytes
,
/* Length of request */
wb_count
;
/* reference count */
wb_bytes
;
/* Length of request */
atomic_t
wb_count
;
/* reference count */
unsigned
long
wb_flags
;
struct
nfs_writeverf
wb_verf
;
/* Commit cookie */
};
...
...
@@ -65,8 +65,6 @@ extern int nfs_coalesce_requests(struct list_head *, struct list_head *,
unsigned
int
);
extern
int
nfs_wait_on_request
(
struct
nfs_page
*
);
extern
spinlock_t
nfs_wreq_lock
;
/*
* Lock the page of an asynchronous request without incrementing the wb_count
*/
...
...
@@ -86,7 +84,7 @@ nfs_lock_request(struct nfs_page *req)
{
if
(
test_and_set_bit
(
PG_BUSY
,
&
req
->
wb_flags
))
return
0
;
req
->
wb_count
++
;
atomic_inc
(
&
req
->
wb_count
)
;
return
1
;
}
...
...
include/linux/nfs_xdr.h
View file @
ecebe0fc
...
...
@@ -657,6 +657,8 @@ struct nfs_write_data {
void
(
*
complete
)
(
struct
nfs_write_data
*
,
int
);
};
struct
nfs_access_entry
;
/*
* RPC procedure vector for NFSv2/NFSv3 demuxing
*/
...
...
@@ -672,7 +674,7 @@ struct nfs_rpc_ops {
struct
iattr
*
);
int
(
*
lookup
)
(
struct
inode
*
,
struct
qstr
*
,
struct
nfs_fh
*
,
struct
nfs_fattr
*
);
int
(
*
access
)
(
struct
inode
*
,
struct
rpc_cred
*
,
int
);
int
(
*
access
)
(
struct
inode
*
,
struct
nfs_access_entry
*
);
int
(
*
readlink
)(
struct
inode
*
,
struct
page
*
);
int
(
*
read
)
(
struct
nfs_read_data
*
,
struct
file
*
);
int
(
*
write
)
(
struct
nfs_write_data
*
,
struct
file
*
);
...
...
include/linux/sunrpc/gss_asn1.h
View file @
ecebe0fc
...
...
@@ -69,7 +69,6 @@ u32 g_verify_token_header(
struct
xdr_netobj
*
mech
,
int
*
body_size
,
unsigned
char
**
buf_in
,
int
tok_type
,
int
toksize
);
u32
g_get_mech_oid
(
struct
xdr_netobj
*
mech
,
struct
xdr_netobj
*
in_buf
);
...
...
include/linux/sunrpc/gss_spkm3.h
0 → 100644
View file @
ecebe0fc
/*
* linux/include/linux/sunrpc/gss_spkm3.h
*
* Copyright (c) 2000 The Regents of the University of Michigan.
* All rights reserved.
*
* Andy Adamson <andros@umich.edu>
*/
#include <linux/sunrpc/auth_gss.h>
#include <linux/sunrpc/gss_err.h>
#include <linux/sunrpc/gss_asn1.h>
struct
spkm3_ctx
{
struct
xdr_netobj
ctx_id
;
/* per message context id */
int
qop
;
/* negotiated qop */
struct
xdr_netobj
mech_used
;
unsigned
int
ret_flags
;
unsigned
int
req_flags
;
struct
xdr_netobj
share_key
;
int
conf_alg
;
struct
crypto_tfm
*
derived_conf_key
;
int
intg_alg
;
struct
crypto_tfm
*
derived_integ_key
;
int
keyestb_alg
;
/* alg used to get share_key */
int
owf_alg
;
/* one way function */
};
/* from openssl/objects.h */
/* XXX need SEAL_ALG_NONE */
#define NID_md5 4
#define NID_dhKeyAgreement 28
#define NID_des_cbc 31
#define NID_sha1 64
#define NID_cast5_cbc 108
/* SPKM InnerContext Token types */
#define SPKM_ERROR_TOK 3
#define SPKM_MIC_TOK 4
#define SPKM_WRAP_TOK 5
#define SPKM_DEL_TOK 6
u32
spkm3_make_token
(
struct
spkm3_ctx
*
ctx
,
int
qop_req
,
struct
xdr_buf
*
text
,
struct
xdr_netobj
*
token
,
int
toktype
);
u32
spkm3_read_token
(
struct
spkm3_ctx
*
ctx
,
struct
xdr_netobj
*
read_token
,
struct
xdr_buf
*
message_buffer
,
int
*
qop_state
,
int
toktype
);
#define CKSUMTYPE_RSA_MD5 0x0007
s32
make_checksum
(
s32
cksumtype
,
char
*
header
,
int
hdrlen
,
struct
xdr_buf
*
body
,
struct
xdr_netobj
*
cksum
);
void
asn1_bitstring_len
(
struct
xdr_netobj
*
in
,
int
*
enclen
,
int
*
zerobits
);
int
decode_asn1_bitstring
(
struct
xdr_netobj
*
out
,
char
*
in
,
int
enclen
,
int
explen
);
void
spkm3_mic_header
(
unsigned
char
**
hdrbuf
,
unsigned
int
*
hdrlen
,
unsigned
char
*
ctxhdr
,
int
elen
,
int
zbit
);
void
spkm3_make_mic_token
(
unsigned
char
**
tokp
,
int
toklen
,
struct
xdr_netobj
*
mic_hdr
,
struct
xdr_netobj
*
md5cksum
,
int
md5elen
,
int
md5zbit
);
u32
spkm3_verify_mic_token
(
unsigned
char
**
tokp
,
int
*
mic_hdrlen
,
unsigned
char
**
cksum
);
net/sunrpc/auth_gss/Makefile
View file @
ecebe0fc
...
...
@@ -12,3 +12,7 @@ obj-$(CONFIG_RPCSEC_GSS_KRB5) += rpcsec_gss_krb5.o
rpcsec_gss_krb5-objs
:=
gss_krb5_mech.o gss_krb5_seal.o gss_krb5_unseal.o
\
gss_krb5_seqnum.o
obj-$(CONFIG_RPCSEC_GSS_SPKM3)
+=
rpcsec_gss_spkm3.o
rpcsec_gss_spkm3-objs
:=
gss_spkm3_mech.o gss_spkm3_seal.o gss_spkm3_unseal.o
\
gss_spkm3_token.o
net/sunrpc/auth_gss/auth_gss.c
View file @
ecebe0fc
...
...
@@ -397,7 +397,7 @@ gss_upcall(struct rpc_clnt *clnt, struct rpc_task *task, struct rpc_cred *cred)
spin_unlock
(
&
gss_auth
->
lock
);
}
gss_release_msg
(
gss_msg
);
dprintk
(
"RPC: %4u gss_upcall for uid %u result %d"
,
task
->
tk_pid
,
dprintk
(
"RPC: %4u gss_upcall for uid %u result %d
\n
"
,
task
->
tk_pid
,
uid
,
res
);
return
res
;
out_sleep:
...
...
net/sunrpc/auth_gss/gss_generic_token.c
View file @
ecebe0fc
...
...
@@ -179,7 +179,7 @@ EXPORT_SYMBOL(g_make_token_header);
*/
u32
g_verify_token_header
(
struct
xdr_netobj
*
mech
,
int
*
body_size
,
unsigned
char
**
buf_in
,
int
tok
_type
,
int
tok
size
)
unsigned
char
**
buf_in
,
int
toksize
)
{
unsigned
char
*
buf
=
*
buf_in
;
int
seqsize
;
...
...
net/sunrpc/auth_gss/gss_krb5_unseal.c
View file @
ecebe0fc
...
...
@@ -96,7 +96,7 @@ krb5_read_token(struct krb5_ctx *ctx,
dprintk
(
"RPC: krb5_read_token
\n
"
);
if
(
g_verify_token_header
(
&
ctx
->
mech_used
,
&
bodysize
,
&
ptr
,
toktype
,
if
(
g_verify_token_header
(
&
ctx
->
mech_used
,
&
bodysize
,
&
ptr
,
read_token
->
len
))
goto
out
;
...
...
net/sunrpc/auth_gss/gss_spkm3_mech.c
0 → 100644
View file @
ecebe0fc
/*
* linux/net/sunrpc/gss_spkm3_mech.c
*
* Copyright (c) 2003 The Regents of the University of Michigan.
* All rights reserved.
*
* Andy Adamson <andros@umich.edu>
* J. Bruce Fields <bfields@umich.edu>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/sunrpc/auth.h>
#include <linux/in.h>
#include <linux/sunrpc/svcauth_gss.h>
#include <linux/sunrpc/gss_spkm3.h>
#include <linux/sunrpc/xdr.h>
#include <linux/crypto.h>
#ifdef RPC_DEBUG
# define RPCDBG_FACILITY RPCDBG_AUTH
#endif
struct
xdr_netobj
gss_mech_spkm3_oid
=
{
7
,
"
\053\006\001\005\005\001\003
"
};
static
inline
int
get_bytes
(
char
**
ptr
,
const
char
*
end
,
void
*
res
,
int
len
)
{
char
*
p
,
*
q
;
p
=
*
ptr
;
q
=
p
+
len
;
if
(
q
>
end
||
q
<
p
)
return
-
1
;
memcpy
(
res
,
p
,
len
);
*
ptr
=
q
;
return
0
;
}
static
inline
int
get_netobj
(
char
**
ptr
,
const
char
*
end
,
struct
xdr_netobj
*
res
)
{
char
*
p
,
*
q
;
p
=
*
ptr
;
if
(
get_bytes
(
&
p
,
end
,
&
res
->
len
,
sizeof
(
res
->
len
)))
return
-
1
;
q
=
p
+
res
->
len
;
if
(
res
->
len
==
0
)
goto
out_nocopy
;
if
(
q
>
end
||
q
<
p
)
return
-
1
;
if
(
!
(
res
->
data
=
kmalloc
(
res
->
len
,
GFP_KERNEL
)))
return
-
1
;
memcpy
(
res
->
data
,
p
,
res
->
len
);
out_nocopy:
*
ptr
=
q
;
return
0
;
}
static
inline
int
get_key
(
char
**
p
,
char
*
end
,
struct
crypto_tfm
**
res
,
int
*
resalg
)
{
struct
xdr_netobj
key
=
{
.
len
=
0
,
.
data
=
NULL
,
};
int
alg_mode
,
setkey
=
0
;
char
*
alg_name
;
if
(
get_bytes
(
p
,
end
,
resalg
,
sizeof
(
int
)))
goto
out_err
;
if
((
get_netobj
(
p
,
end
,
&
key
)))
goto
out_err
;
switch
(
*
resalg
)
{
case
NID_des_cbc
:
alg_name
=
"des"
;
alg_mode
=
CRYPTO_TFM_MODE_CBC
;
setkey
=
1
;
break
;
case
NID_md5
:
if
(
key
.
len
==
0
)
{
dprintk
(
"RPC: SPKM3 get_key: NID_md5 zero Key length
\n
"
);
}
alg_name
=
"md5"
;
alg_mode
=
0
;
setkey
=
0
;
break
;
case
NID_cast5_cbc
:
dprintk
(
"RPC: SPKM3 get_key: case cast5_cbc, UNSUPPORTED
\n
"
);
goto
out_err
;
break
;
default:
dprintk
(
"RPC: SPKM3 get_key: unsupported algorithm %d"
,
*
resalg
);
goto
out_err_free_key
;
}
if
(
!
(
*
res
=
crypto_alloc_tfm
(
alg_name
,
alg_mode
)))
goto
out_err_free_key
;
if
(
setkey
)
{
if
(
crypto_cipher_setkey
(
*
res
,
key
.
data
,
key
.
len
))
goto
out_err_free_tfm
;
}
if
(
key
.
len
>
0
)
kfree
(
key
.
data
);
return
0
;
out_err_free_tfm:
crypto_free_tfm
(
*
res
);
out_err_free_key:
if
(
key
.
len
>
0
)
kfree
(
key
.
data
);
out_err:
return
-
1
;
}
static
u32
gss_import_sec_context_spkm3
(
struct
xdr_netobj
*
inbuf
,
struct
gss_ctx
*
ctx_id
)
{
char
*
p
=
inbuf
->
data
;
char
*
end
=
inbuf
->
data
+
inbuf
->
len
;
struct
spkm3_ctx
*
ctx
;
if
(
!
(
ctx
=
kmalloc
(
sizeof
(
*
ctx
),
GFP_KERNEL
)))
goto
out_err
;
memset
(
ctx
,
0
,
sizeof
(
*
ctx
));
if
(
get_netobj
(
&
p
,
end
,
&
ctx
->
ctx_id
))
goto
out_err_free_ctx
;
if
(
get_bytes
(
&
p
,
end
,
&
ctx
->
qop
,
sizeof
(
ctx
->
qop
)))
goto
out_err_free_ctx_id
;
if
(
get_netobj
(
&
p
,
end
,
&
ctx
->
mech_used
))
goto
out_err_free_mech
;
if
(
get_bytes
(
&
p
,
end
,
&
ctx
->
ret_flags
,
sizeof
(
ctx
->
ret_flags
)))
goto
out_err_free_mech
;
if
(
get_bytes
(
&
p
,
end
,
&
ctx
->
req_flags
,
sizeof
(
ctx
->
req_flags
)))
goto
out_err_free_mech
;
if
(
get_netobj
(
&
p
,
end
,
&
ctx
->
share_key
))
goto
out_err_free_s_key
;
if
(
get_key
(
&
p
,
end
,
&
ctx
->
derived_conf_key
,
&
ctx
->
conf_alg
))
{
dprintk
(
"RPC: SPKM3 confidentiality key will be NULL
\n
"
);
}
if
(
get_key
(
&
p
,
end
,
&
ctx
->
derived_integ_key
,
&
ctx
->
intg_alg
))
{
dprintk
(
"RPC: SPKM3 integrity key will be NULL
\n
"
);
}
if
(
get_bytes
(
&
p
,
end
,
&
ctx
->
owf_alg
,
sizeof
(
ctx
->
owf_alg
)))
goto
out_err_free_s_key
;
if
(
get_bytes
(
&
p
,
end
,
&
ctx
->
owf_alg
,
sizeof
(
ctx
->
owf_alg
)))
goto
out_err_free_s_key
;
if
(
p
!=
end
)
goto
out_err_free_s_key
;
ctx_id
->
internal_ctx_id
=
ctx
;
dprintk
(
"Succesfully imported new spkm context.
\n
"
);
return
0
;
out_err_free_s_key:
kfree
(
ctx
->
share_key
.
data
);
out_err_free_mech:
kfree
(
ctx
->
mech_used
.
data
);
out_err_free_ctx_id:
kfree
(
ctx
->
ctx_id
.
data
);
out_err_free_ctx:
kfree
(
ctx
);
out_err:
return
GSS_S_FAILURE
;
}
void
gss_delete_sec_context_spkm3
(
void
*
internal_ctx
)
{
struct
spkm3_ctx
*
sctx
=
internal_ctx
;
if
(
sctx
->
derived_integ_key
)
crypto_free_tfm
(
sctx
->
derived_integ_key
);
if
(
sctx
->
derived_conf_key
)
crypto_free_tfm
(
sctx
->
derived_conf_key
);
if
(
sctx
->
share_key
.
data
)
kfree
(
sctx
->
share_key
.
data
);
if
(
sctx
->
mech_used
.
data
)
kfree
(
sctx
->
mech_used
.
data
);
kfree
(
sctx
);
}
u32
gss_verify_mic_spkm3
(
struct
gss_ctx
*
ctx
,
struct
xdr_buf
*
signbuf
,
struct
xdr_netobj
*
checksum
,
u32
*
qstate
)
{
u32
maj_stat
=
0
;
int
qop_state
=
0
;
struct
spkm3_ctx
*
sctx
=
ctx
->
internal_ctx_id
;
dprintk
(
"RPC: gss_verify_mic_spkm3 calling spkm3_read_token
\n
"
);
maj_stat
=
spkm3_read_token
(
sctx
,
checksum
,
signbuf
,
&
qop_state
,
SPKM_MIC_TOK
);
if
(
!
maj_stat
&&
qop_state
)
*
qstate
=
qop_state
;
dprintk
(
"RPC: gss_verify_mic_spkm3 returning %d
\n
"
,
maj_stat
);
return
maj_stat
;
}
u32
gss_get_mic_spkm3
(
struct
gss_ctx
*
ctx
,
u32
qop
,
struct
xdr_buf
*
message_buffer
,
struct
xdr_netobj
*
message_token
)
{
u32
err
=
0
;
struct
spkm3_ctx
*
sctx
=
ctx
->
internal_ctx_id
;
dprintk
(
"RPC: gss_get_mic_spkm3
\n
"
);
err
=
spkm3_make_token
(
sctx
,
qop
,
message_buffer
,
message_token
,
SPKM_MIC_TOK
);
return
err
;
}
static
struct
gss_api_ops
gss_spkm3_ops
=
{
.
gss_import_sec_context
=
gss_import_sec_context_spkm3
,
.
gss_get_mic
=
gss_get_mic_spkm3
,
.
gss_verify_mic
=
gss_verify_mic_spkm3
,
.
gss_delete_sec_context
=
gss_delete_sec_context_spkm3
,
};
static
struct
pf_desc
gss_spkm3_pfs
[]
=
{
{
RPC_AUTH_GSS_SPKM
,
0
,
RPC_GSS_SVC_NONE
,
"spkm3"
},
{
RPC_AUTH_GSS_SPKMI
,
0
,
RPC_GSS_SVC_INTEGRITY
,
"spkm3i"
},
};
static
struct
gss_api_mech
gss_spkm3_mech
=
{
.
gm_name
=
"spkm3"
,
.
gm_owner
=
THIS_MODULE
,
.
gm_ops
=
&
gss_spkm3_ops
,
.
gm_pf_num
=
ARRAY_SIZE
(
gss_spkm3_pfs
),
.
gm_pfs
=
gss_spkm3_pfs
,
};
static
int
__init
init_spkm3_module
(
void
)
{
int
status
;
status
=
gss_mech_register
(
&
gss_spkm3_mech
);
if
(
status
)
printk
(
"Failed to register spkm3 gss mechanism!
\n
"
);
return
0
;
}
static
void
__exit
cleanup_spkm3_module
(
void
)
{
gss_mech_unregister
(
&
gss_spkm3_mech
);
}
MODULE_LICENSE
(
"GPL"
);
module_init
(
init_spkm3_module
);
module_exit
(
cleanup_spkm3_module
);
net/sunrpc/auth_gss/gss_spkm3_seal.c
0 → 100644
View file @
ecebe0fc
/*
* linux/net/sunrpc/gss_spkm3_seal.c
*
* Copyright (c) 2003 The Regents of the University of Michigan.
* All rights reserved.
*
* Andy Adamson <andros@umich.edu>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/sunrpc/gss_spkm3.h>
#include <linux/random.h>
#include <linux/crypto.h>
#ifdef RPC_DEBUG
# define RPCDBG_FACILITY RPCDBG_AUTH
#endif
/*
* spkm3_make_token()
*
* Only SPKM_MIC_TOK with md5 intg-alg is supported
*/
u32
spkm3_make_token
(
struct
spkm3_ctx
*
ctx
,
int
qop_req
,
struct
xdr_buf
*
text
,
struct
xdr_netobj
*
token
,
int
toktype
)
{
s32
checksum_type
;
char
tokhdrbuf
[
25
];
struct
xdr_netobj
md5cksum
=
{.
len
=
0
,
.
data
=
NULL
};
struct
xdr_netobj
mic_hdr
=
{.
len
=
0
,
.
data
=
tokhdrbuf
};
int
tmsglen
,
tokenlen
=
0
;
unsigned
char
*
ptr
;
s32
now
;
int
ctxelen
=
0
,
ctxzbit
=
0
;
int
md5elen
=
0
,
md5zbit
=
0
;
dprintk
(
"RPC: spkm3_make_token
\n
"
);
now
=
jiffies
;
if
(
qop_req
!=
0
)
goto
out_err
;
if
(
ctx
->
ctx_id
.
len
!=
16
)
{
dprintk
(
"RPC: spkm3_make_token BAD ctx_id.len %d
\n
"
,
ctx
->
ctx_id
.
len
);
goto
out_err
;
}
switch
(
ctx
->
intg_alg
)
{
case
NID_md5
:
checksum_type
=
CKSUMTYPE_RSA_MD5
;
break
;
default:
dprintk
(
"RPC: gss_spkm3_seal: ctx->signalg %d not"
" supported
\n
"
,
ctx
->
intg_alg
);
goto
out_err
;
}
/* XXX since we don't support WRAP, perhaps we don't care... */
if
(
ctx
->
conf_alg
!=
NID_cast5_cbc
)
{
dprintk
(
"RPC: gss_spkm3_seal: ctx->sealalg %d not supported
\n
"
,
ctx
->
conf_alg
);
goto
out_err
;
}
if
(
toktype
==
SPKM_MIC_TOK
)
{
tmsglen
=
0
;
/* Calculate checksum over the mic-header */
asn1_bitstring_len
(
&
ctx
->
ctx_id
,
&
ctxelen
,
&
ctxzbit
);
spkm3_mic_header
(
&
mic_hdr
.
data
,
&
mic_hdr
.
len
,
ctx
->
ctx_id
.
data
,
ctxelen
,
ctxzbit
);
if
(
make_checksum
(
checksum_type
,
mic_hdr
.
data
,
mic_hdr
.
len
,
text
,
&
md5cksum
))
goto
out_err
;
asn1_bitstring_len
(
&
md5cksum
,
&
md5elen
,
&
md5zbit
);
tokenlen
=
10
+
ctxelen
+
1
+
2
+
md5elen
+
1
;
/* Create token header using generic routines */
token
->
len
=
g_token_size
(
&
ctx
->
mech_used
,
tokenlen
+
tmsglen
);
ptr
=
token
->
data
;
g_make_token_header
(
&
ctx
->
mech_used
,
tokenlen
+
tmsglen
,
&
ptr
);
spkm3_make_mic_token
(
&
ptr
,
tokenlen
,
&
mic_hdr
,
&
md5cksum
,
md5elen
,
md5zbit
);
}
else
if
(
toktype
==
SPKM_WRAP_TOK
)
{
/* Not Supported */
dprintk
(
"RPC: gss_spkm3_seal: SPKM_WRAP_TOK not supported
\n
"
);
goto
out_err
;
}
kfree
(
md5cksum
.
data
);
/* XXX need to implement sequence numbers, and ctx->expired */
return
GSS_S_COMPLETE
;
out_err:
if
(
md5cksum
.
data
)
kfree
(
md5cksum
.
data
);
token
->
data
=
0
;
token
->
len
=
0
;
return
GSS_S_FAILURE
;
}
net/sunrpc/auth_gss/gss_spkm3_token.c
0 → 100644
View file @
ecebe0fc
/*
* linux/net/sunrpc/gss_spkm3_token.c
*
* Copyright (c) 2003 The Regents of the University of Michigan.
* All rights reserved.
*
* Andy Adamson <andros@umich.edu>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/sunrpc/gss_spkm3.h>
#include <linux/random.h>
#include <linux/crypto.h>
#ifdef RPC_DEBUG
# define RPCDBG_FACILITY RPCDBG_AUTH
#endif
/*
* asn1_bitstring_len()
*
* calculate the asn1 bitstring length of the xdr_netobject
*/
void
asn1_bitstring_len
(
struct
xdr_netobj
*
in
,
int
*
enclen
,
int
*
zerobits
)
{
int
i
,
zbit
=
0
,
elen
=
in
->
len
;
char
*
ptr
;
ptr
=
&
in
->
data
[
in
->
len
-
1
];
/* count trailing 0's */
for
(
i
=
in
->
len
;
i
>
0
;
i
--
)
{
if
(
*
ptr
==
0
)
{
ptr
--
;
elen
--
;
}
else
break
;
}
/* count number of 0 bits in final octet */
ptr
=
&
in
->
data
[
elen
-
1
];
for
(
i
=
0
;
i
<
8
;
i
++
)
{
short
mask
=
0x01
;
if
(
!
((
mask
<<
i
)
&
*
ptr
))
zbit
++
;
else
break
;
}
*
enclen
=
elen
;
*
zerobits
=
zbit
;
}
/*
* decode_asn1_bitstring()
*
* decode a bitstring into a buffer of the expected length.
* enclen = bit string length
* explen = expected length (define in rfc)
*/
int
decode_asn1_bitstring
(
struct
xdr_netobj
*
out
,
char
*
in
,
int
enclen
,
int
explen
)
{
if
(
!
(
out
->
data
=
kmalloc
(
explen
,
GFP_KERNEL
)))
return
0
;
out
->
len
=
explen
;
memset
(
out
->
data
,
0
,
explen
);
memcpy
(
out
->
data
,
in
,
enclen
);
return
1
;
}
/*
* SPKMInnerContextToken choice SPKM_MIC asn1 token layout
*
* contextid is always 16 bytes plain data. max asn1 bitstring len = 17.
*
* tokenlen = pos[0] to end of token (max pos[45] with MD5 cksum)
*
* pos value
* ----------
* [0] a4 SPKM-MIC tag
* [1] ?? innertoken length (max 44)
*
*
* tok_hdr piece of checksum data starts here
*
* the maximum mic-header len = 9 + 17 = 26
* mic-header
* ----------
* [2] 30 SEQUENCE tag
* [3] ?? mic-header length: (max 23) = TokenID + ContextID
*
* TokenID - all fields constant and can be hardcoded
* -------
* [4] 02 Type 2
* [5] 02 Length 2
* [6][7] 01 01 TokenID (SPKM_MIC_TOK)
*
* ContextID - encoded length not constant, calculated
* ---------
* [8] 03 Type 3
* [9] ?? encoded length
* [10] ?? ctxzbit
* [11] contextid
*
* mic_header piece of checksum data ends here.
*
* int-cksum - encoded length not constant, calculated
* ---------
* [??] 03 Type 3
* [??] ?? encoded length
* [??] ?? md5zbit
* [??] int-cksum (NID_md5 = 16)
*
* maximum SPKM-MIC innercontext token length =
* 10 + encoded contextid_size(17 max) + 2 + encoded
* cksum_size (17 maxfor NID_md5) = 46
*/
/*
* spkm3_mic_header()
*
* Prepare the SPKM_MIC_TOK mic-header for check-sum calculation
* elen: 16 byte context id asn1 bitstring encoded length
*/
void
spkm3_mic_header
(
unsigned
char
**
hdrbuf
,
unsigned
int
*
hdrlen
,
unsigned
char
*
ctxdata
,
int
elen
,
int
zbit
)
{
char
*
hptr
=
*
hdrbuf
;
char
*
top
=
*
hdrbuf
;
*
(
u8
*
)
hptr
++
=
0x30
;
*
(
u8
*
)
hptr
++
=
elen
+
7
;
/* on the wire header length */
/* tokenid */
*
(
u8
*
)
hptr
++
=
0x02
;
*
(
u8
*
)
hptr
++
=
0x02
;
*
(
u8
*
)
hptr
++
=
0x01
;
*
(
u8
*
)
hptr
++
=
0x01
;
/* coniextid */
*
(
u8
*
)
hptr
++
=
0x03
;
*
(
u8
*
)
hptr
++
=
elen
+
1
;
/* add 1 to include zbit */
*
(
u8
*
)
hptr
++
=
zbit
;
memcpy
(
hptr
,
ctxdata
,
elen
);
hptr
+=
elen
;
*
hdrlen
=
hptr
-
top
;
}
/*
* spkm3_mic_innercontext_token()
*
* *tokp points to the beginning of the SPKM_MIC token described
* in rfc 2025, section 3.2.1:
*
*/
void
spkm3_make_mic_token
(
unsigned
char
**
tokp
,
int
toklen
,
struct
xdr_netobj
*
mic_hdr
,
struct
xdr_netobj
*
md5cksum
,
int
md5elen
,
int
md5zbit
)
{
unsigned
char
*
ict
=
*
tokp
;
*
(
u8
*
)
ict
++
=
0xa4
;
*
(
u8
*
)
ict
++
=
toklen
-
2
;
memcpy
(
ict
,
mic_hdr
->
data
,
mic_hdr
->
len
);
ict
+=
mic_hdr
->
len
;
*
(
u8
*
)
ict
++
=
0x03
;
*
(
u8
*
)
ict
++
=
md5elen
+
1
;
/* add 1 to include zbit */
*
(
u8
*
)
ict
++
=
md5zbit
;
memcpy
(
ict
,
md5cksum
->
data
,
md5elen
);
}
u32
spkm3_verify_mic_token
(
unsigned
char
**
tokp
,
int
*
mic_hdrlen
,
unsigned
char
**
cksum
)
{
struct
xdr_netobj
spkm3_ctx_id
=
{.
len
=
0
,
.
data
=
NULL
};
unsigned
char
*
ptr
=
*
tokp
;
int
ctxelen
;
u32
ret
=
GSS_S_DEFECTIVE_TOKEN
;
/* spkm3 innercontext token preamble */
if
((
ptr
[
0
]
!=
0xa4
)
||
(
ptr
[
2
]
!=
0x30
))
{
dprintk
(
"RPC: BAD SPKM ictoken preamble
\n
"
);
goto
out
;
}
*
mic_hdrlen
=
ptr
[
3
];
/* token type */
if
((
ptr
[
4
]
!=
0x02
)
||
(
ptr
[
5
]
!=
0x02
))
{
dprintk
(
"RPC: BAD asn1 SPKM3 token type
\n
"
);
goto
out
;
}
/* only support SPKM_MIC_TOK */
if
((
ptr
[
6
]
!=
0x01
)
||
(
ptr
[
7
]
!=
0x01
))
{
dprintk
(
"RPC: ERROR unsupported SPKM3 token
\n
"
);
goto
out
;
}
/* contextid */
if
(
ptr
[
8
]
!=
0x03
)
{
dprintk
(
"RPC: BAD SPKM3 asn1 context-id type
\n
"
);
goto
out
;
}
ctxelen
=
ptr
[
9
];
if
(
ctxelen
>
17
)
{
/* length includes asn1 zbit octet */
dprintk
(
"RPC: BAD SPKM3 contextid len %d
\n
"
,
ctxelen
);
goto
out
;
}
/* ignore ptr[10] */
if
(
!
decode_asn1_bitstring
(
&
spkm3_ctx_id
,
&
ptr
[
11
],
ctxelen
-
1
,
16
))
goto
out
;
/*
* in the current implementation: the optional int-alg is not present
* so the default int-alg (md5) is used the optional snd-seq field is
* also not present
*/
if
(
*
mic_hdrlen
!=
6
+
ctxelen
)
{
dprintk
(
"RPC: BAD SPKM_ MIC_TOK header len %d: we only support default int-alg (should be absent) and do not support snd-seq
\n
"
,
*
mic_hdrlen
);
goto
out
;
}
/* checksum */
*
cksum
=
(
&
ptr
[
10
]
+
ctxelen
);
/* ctxelen includes ptr[10] */
ret
=
GSS_S_COMPLETE
;
out:
if
(
spkm3_ctx_id
.
data
)
kfree
(
spkm3_ctx_id
.
data
);
return
ret
;
}
net/sunrpc/auth_gss/gss_spkm3_unseal.c
0 → 100644
View file @
ecebe0fc
/*
* linux/net/sunrpc/gss_spkm3_unseal.c
*
* Copyright (c) 2003 The Regents of the University of Michigan.
* All rights reserved.
*
* Andy Adamson <andros@umich.edu>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/sunrpc/gss_spkm3.h>
#include <linux/crypto.h>
#ifdef RPC_DEBUG
# define RPCDBG_FACILITY RPCDBG_AUTH
#endif
/*
* spkm3_read_token()
*
* only SPKM_MIC_TOK with md5 intg-alg is supported
*/
u32
spkm3_read_token
(
struct
spkm3_ctx
*
ctx
,
struct
xdr_netobj
*
read_token
,
/* checksum */
struct
xdr_buf
*
message_buffer
,
/* signbuf */
int
*
qop_state
,
int
toktype
)
{
s32
code
;
struct
xdr_netobj
wire_cksum
=
{.
len
=
0
,
.
data
=
NULL
};
struct
xdr_netobj
md5cksum
=
{.
len
=
0
,
.
data
=
NULL
};
unsigned
char
*
ptr
=
(
unsigned
char
*
)
read_token
->
data
;
unsigned
char
*
cksum
;
int
bodysize
,
md5elen
;
int
mic_hdrlen
;
u32
ret
=
GSS_S_DEFECTIVE_TOKEN
;
dprintk
(
"RPC: spkm3_read_token read_token->len %d
\n
"
,
read_token
->
len
);
if
(
g_verify_token_header
((
struct
xdr_netobj
*
)
&
ctx
->
mech_used
,
&
bodysize
,
&
ptr
,
read_token
->
len
))
goto
out
;
/* decode the token */
if
(
toktype
==
SPKM_MIC_TOK
)
{
if
((
ret
=
spkm3_verify_mic_token
(
&
ptr
,
&
mic_hdrlen
,
&
cksum
)))
goto
out
;
if
(
*
cksum
++
!=
0x03
)
{
dprintk
(
"RPC: spkm3_read_token BAD checksum type
\n
"
);
goto
out
;
}
md5elen
=
*
cksum
++
;
cksum
++
;
/* move past the zbit */
if
(
!
decode_asn1_bitstring
(
&
wire_cksum
,
cksum
,
md5elen
-
1
,
16
))
goto
out
;
/* HARD CODED FOR MD5 */
/* compute the checksum of the message.
* ptr + 2 = start of header piece of checksum
* mic_hdrlen + 2 = length of header piece of checksum
*/
ret
=
GSS_S_DEFECTIVE_TOKEN
;
code
=
make_checksum
(
CKSUMTYPE_RSA_MD5
,
ptr
+
2
,
mic_hdrlen
+
2
,
message_buffer
,
&
md5cksum
);
if
(
code
)
goto
out
;
dprintk
(
"RPC: spkm3_read_token: digest wire_cksum.len %d:
\n
"
,
wire_cksum
.
len
);
dprintk
(
" md5cksum.data
\n
"
);
print_hexl
((
u32
*
)
md5cksum
.
data
,
16
,
0
);
dprintk
(
" cksum.data:
\n
"
);
print_hexl
((
u32
*
)
wire_cksum
.
data
,
wire_cksum
.
len
,
0
);
ret
=
GSS_S_BAD_SIG
;
code
=
memcmp
(
md5cksum
.
data
,
wire_cksum
.
data
,
wire_cksum
.
len
);
if
(
code
)
goto
out
;
}
else
{
dprintk
(
"RPC: BAD or UNSUPPORTED SPKM3 token type: %d
\n
"
,
toktype
);
goto
out
;
}
/* XXX: need to add expiration and sequencing */
ret
=
GSS_S_COMPLETE
;
out:
if
(
md5cksum
.
data
)
kfree
(
md5cksum
.
data
);
if
(
wire_cksum
.
data
)
kfree
(
wire_cksum
.
data
);
return
ret
;
}
net/sunrpc/clnt.c
View file @
ecebe0fc
...
...
@@ -196,7 +196,15 @@ rpc_clone_client(struct rpc_clnt *clnt)
memcpy
(
new
,
clnt
,
sizeof
(
*
new
));
atomic_set
(
&
new
->
cl_count
,
1
);
atomic_set
(
&
new
->
cl_users
,
0
);
atomic_inc
(
&
new
->
cl_parent
->
cl_count
);
new
->
cl_parent
=
clnt
;
atomic_inc
(
&
clnt
->
cl_count
);
/* Duplicate portmapper */
rpc_init_wait_queue
(
&
new
->
cl_pmap_default
.
pm_bindwait
,
"bindwait"
);
/* Turn off autobind on clones */
new
->
cl_autobind
=
0
;
new
->
cl_oneshot
=
0
;
new
->
cl_dead
=
0
;
rpc_init_rtt
(
&
new
->
cl_rtt_default
,
clnt
->
cl_xprt
->
timeout
.
to_initval
);
if
(
new
->
cl_auth
)
atomic_inc
(
&
new
->
cl_auth
->
au_count
);
return
new
;
...
...
@@ -335,7 +343,7 @@ void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset)
*/
int
rpc_call_sync
(
struct
rpc_clnt
*
clnt
,
struct
rpc_message
*
msg
,
int
flags
)
{
struct
rpc_task
my_task
,
*
task
=
&
my_
task
;
struct
rpc_task
*
task
;
sigset_t
oldset
;
int
status
;
...
...
@@ -343,15 +351,15 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
if
(
clnt
->
cl_dead
)
return
-
EIO
;
if
(
flags
&
RPC_TASK_ASYNC
)
{
printk
(
"rpc_call_sync: Illegal flag combination for synchronous task
\n
"
);
flags
&=
~
RPC_TASK_ASYNC
;
}
BUG_ON
(
flags
&
RPC_TASK_ASYNC
);
rpc_clnt_sigmask
(
clnt
,
&
oldset
);
/* Create/initialize a new RPC task */
rpc_init_task
(
task
,
clnt
,
NULL
,
flags
);
status
=
-
ENOMEM
;
task
=
rpc_new_task
(
clnt
,
NULL
,
flags
);
if
(
task
==
NULL
)
goto
out
;
rpc_call_setup
(
task
,
msg
,
0
);
/* Set up the call info struct and execute the task */
...
...
@@ -362,6 +370,7 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
rpc_release_task
(
task
);
}
out:
rpc_clnt_sigunmask
(
clnt
,
&
oldset
);
return
status
;
...
...
@@ -958,8 +967,12 @@ call_header(struct rpc_task *task)
static
u32
*
call_verify
(
struct
rpc_task
*
task
)
{
u32
*
p
=
task
->
tk_rqstp
->
rq_rcv_buf
.
head
[
0
].
iov_base
,
n
;
struct
kvec
*
iov
=
&
task
->
tk_rqstp
->
rq_rcv_buf
.
head
[
0
];
int
len
=
task
->
tk_rqstp
->
rq_rcv_buf
.
len
>>
2
;
u32
*
p
=
iov
->
iov_base
,
n
;
if
((
len
-=
3
)
<
0
)
goto
garbage
;
p
+=
1
;
/* skip XID */
if
((
n
=
ntohl
(
*
p
++
))
!=
RPC_REPLY
)
{
...
...
@@ -969,9 +982,11 @@ call_verify(struct rpc_task *task)
if
((
n
=
ntohl
(
*
p
++
))
!=
RPC_MSG_ACCEPTED
)
{
int
error
=
-
EACCES
;
if
(
--
len
<
0
)
goto
garbage
;
if
((
n
=
ntohl
(
*
p
++
))
!=
RPC_AUTH_ERROR
)
{
printk
(
KERN_WARNING
"call_verify: RPC call rejected: %x
\n
"
,
n
);
}
else
}
else
if
(
--
len
<
0
)
switch
((
n
=
ntohl
(
*
p
++
)))
{
case
RPC_AUTH_REJECTEDCRED
:
case
RPC_AUTH_REJECTEDVERF
:
...
...
@@ -1002,7 +1017,8 @@ call_verify(struct rpc_task *task)
default:
printk
(
KERN_WARNING
"call_verify: unknown auth error: %x
\n
"
,
n
);
error
=
-
EIO
;
}
}
else
goto
garbage
;
dprintk
(
"RPC: %4d call_verify: call rejected %d
\n
"
,
task
->
tk_pid
,
n
);
rpc_exit
(
task
,
error
);
...
...
@@ -1012,6 +1028,9 @@ call_verify(struct rpc_task *task)
printk
(
KERN_WARNING
"call_verify: auth check failed
\n
"
);
goto
garbage
;
/* bad verifier, retry */
}
len
=
p
-
(
u32
*
)
iov
->
iov_base
-
1
;
if
(
len
<
0
)
goto
garbage
;
switch
((
n
=
ntohl
(
*
p
++
)))
{
case
RPC_SUCCESS
:
return
p
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment