Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'nfsd-next' of git://linux-nfs.org/~bfields/linux

Pull nfsd updates from Bruce Fields:
"This was a very quiet cycle! Just a few bugfixes and some cleanup"

* 'nfsd-next' of git://linux-nfs.org/~bfields/linux:
rpc: let xdr layer allocate gssproxy receieve pages
rpc: fix huge kmalloc's in gss-proxy
rpc: comment on linux_cred encoding, treat all as unsigned
rpc: clean up decoding of gssproxy linux creds
svcrpc: remove unused rq_resused
nfsd4: nfsd4_create_clid_dir prints uninitialized data
nfsd4: fix leak of inode reference on delegation failure
Revert "nfsd: nfs4_file_get_access: need to be more careful with O_RDWR"
sunrpc: prepare NFS for 2038
nfsd4: fix setlease error return
nfsd: nfs4_file_get_access: need to be more careful with O_RDWR

+91 -39
-2
fs/nfsd/nfs4recover.c
··· 173 173 int status; 174 174 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 175 175 176 - dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname); 177 - 178 176 if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 179 177 return; 180 178 if (!nn->rec_file)
+21 -12
fs/nfsd/nfs4state.c
··· 368 368 alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh) 369 369 { 370 370 struct nfs4_delegation *dp; 371 - struct nfs4_file *fp = stp->st_file; 372 371 373 372 dprintk("NFSD alloc_init_deleg\n"); 374 - if (fp->fi_had_conflict) 375 - return NULL; 376 373 if (num_delegations > max_delegations) 377 374 return NULL; 378 375 dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab)); ··· 386 389 INIT_LIST_HEAD(&dp->dl_perfile); 387 390 INIT_LIST_HEAD(&dp->dl_perclnt); 388 391 INIT_LIST_HEAD(&dp->dl_recall_lru); 389 - get_nfs4_file(fp); 390 - dp->dl_file = fp; 392 + dp->dl_file = NULL; 391 393 dp->dl_type = NFS4_OPEN_DELEGATE_READ; 392 394 fh_copy_shallow(&dp->dl_fh, &current_fh->fh_handle); 393 395 dp->dl_time = 0; ··· 3031 3035 if (status) { 3032 3036 list_del_init(&dp->dl_perclnt); 3033 3037 locks_free_lock(fl); 3034 - return -ENOMEM; 3038 + return status; 3035 3039 } 3036 3040 fp->fi_lease = fl; 3037 3041 fp->fi_deleg_file = get_file(fl->fl_file); ··· 3040 3044 return 0; 3041 3045 } 3042 3046 3043 - static int nfs4_set_delegation(struct nfs4_delegation *dp) 3047 + static int nfs4_set_delegation(struct nfs4_delegation *dp, struct nfs4_file *fp) 3044 3048 { 3045 - struct nfs4_file *fp = dp->dl_file; 3049 + int status; 3046 3050 3047 - if (!fp->fi_lease) 3048 - return nfs4_setlease(dp); 3051 + if (fp->fi_had_conflict) 3052 + return -EAGAIN; 3053 + get_nfs4_file(fp); 3054 + dp->dl_file = fp; 3055 + if (!fp->fi_lease) { 3056 + status = nfs4_setlease(dp); 3057 + if (status) 3058 + goto out_free; 3059 + return 0; 3060 + } 3049 3061 spin_lock(&recall_lock); 3050 3062 if (fp->fi_had_conflict) { 3051 3063 spin_unlock(&recall_lock); 3052 - return -EAGAIN; 3064 + status = -EAGAIN; 3065 + goto out_free; 3053 3066 } 3054 3067 atomic_inc(&fp->fi_delegees); 3055 3068 list_add(&dp->dl_perfile, &fp->fi_delegations); 3056 3069 spin_unlock(&recall_lock); 3057 3070 list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations); 3058 3071 return 0; 3072 + out_free: 3073 + put_nfs4_file(fp); 3074 + dp->dl_file = fp; 3075 + return status; 3059 3076 } 3060 3077 3061 3078 static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status) ··· 3143 3134 dp = alloc_init_deleg(oo->oo_owner.so_client, stp, fh); 3144 3135 if (dp == NULL) 3145 3136 goto out_no_deleg; 3146 - status = nfs4_set_delegation(dp); 3137 + status = nfs4_set_delegation(dp, stp->st_file); 3147 3138 if (status) 3148 3139 goto out_free; 3149 3140
+20 -2
include/linux/sunrpc/cache.h
··· 264 264 return 0; 265 265 } 266 266 267 + static inline int get_time(char **bpp, time_t *time) 268 + { 269 + char buf[50]; 270 + long long ll; 271 + int len = qword_get(bpp, buf, sizeof(buf)); 272 + 273 + if (len < 0) 274 + return -EINVAL; 275 + if (len == 0) 276 + return -ENOENT; 277 + 278 + if (kstrtoll(buf, 0, &ll)) 279 + return -EINVAL; 280 + 281 + *time = (time_t)ll; 282 + return 0; 283 + } 284 + 267 285 static inline time_t get_expiry(char **bpp) 268 286 { 269 - int rv; 287 + time_t rv; 270 288 struct timespec boot; 271 289 272 - if (get_int(bpp, &rv)) 290 + if (get_time(bpp, &rv)) 273 291 return 0; 274 292 if (rv < 0) 275 293 return 0;
-1
include/linux/sunrpc/svc.h
··· 243 243 struct xdr_buf rq_res; 244 244 struct page * rq_pages[RPCSVC_MAXPAGES]; 245 245 struct page * *rq_respages; /* points into rq_pages */ 246 - int rq_resused; /* number of pages used for result */ 247 246 struct page * *rq_next_page; /* next reply page to use */ 248 247 249 248 struct kvec rq_vec[RPCSVC_MAXPAGES]; /* generally useful.. */
+26
net/sunrpc/auth_gss/gss_rpc_upcall.c
··· 213 213 return status; 214 214 } 215 215 216 + static void gssp_free_receive_pages(struct gssx_arg_accept_sec_context *arg) 217 + { 218 + int i; 219 + 220 + for (i = 0; i < arg->npages && arg->pages[i]; i++) 221 + __free_page(arg->pages[i]); 222 + } 223 + 224 + static int gssp_alloc_receive_pages(struct gssx_arg_accept_sec_context *arg) 225 + { 226 + arg->npages = DIV_ROUND_UP(NGROUPS_MAX * 4, PAGE_SIZE); 227 + arg->pages = kzalloc(arg->npages * sizeof(struct page *), GFP_KERNEL); 228 + /* 229 + * XXX: actual pages are allocated by xdr layer in 230 + * xdr_partial_copy_from_skb. 231 + */ 232 + if (!arg->pages) 233 + return -ENOMEM; 234 + return 0; 235 + } 216 236 217 237 /* 218 238 * Public functions ··· 281 261 arg.context_handle = &ctxh; 282 262 res.output_token->len = GSSX_max_output_token_sz; 283 263 264 + ret = gssp_alloc_receive_pages(&arg); 265 + if (ret) 266 + return ret; 267 + 284 268 /* use nfs/ for targ_name ? */ 285 269 286 270 ret = gssp_call(net, &msg); 271 + 272 + gssp_free_receive_pages(&arg); 287 273 288 274 /* we need to fetch all data even in case of error so 289 275 * that we can free special strctures is they have been allocated */
+20 -21
net/sunrpc/auth_gss/gss_rpc_xdr.c
··· 166 166 return 0; 167 167 } 168 168 169 - static int get_s32(void **p, void *max, s32 *res) 169 + static int get_host_u32(struct xdr_stream *xdr, u32 *res) 170 170 { 171 - void *base = *p; 172 - void *next = (void *)((char *)base + sizeof(s32)); 173 - if (unlikely(next > max || next < base)) 171 + __be32 *p; 172 + 173 + p = xdr_inline_decode(xdr, 4); 174 + if (!p) 174 175 return -EINVAL; 175 - memcpy(res, base, sizeof(s32)); 176 - *p = next; 176 + /* Contents of linux creds are all host-endian: */ 177 + memcpy(res, p, sizeof(u32)); 177 178 return 0; 178 179 } 179 180 ··· 183 182 { 184 183 u32 length; 185 184 __be32 *p; 186 - void *q, *end; 187 - s32 tmp; 188 - int N, i, err; 185 + u32 tmp; 186 + u32 N; 187 + int i, err; 189 188 190 189 p = xdr_inline_decode(xdr, 4); 191 190 if (unlikely(p == NULL)) ··· 193 192 194 193 length = be32_to_cpup(p); 195 194 196 - /* FIXME: we do not want to use the scratch buffer for this one 197 - * may need to use functions that allows us to access an io vector 198 - * directly */ 199 - p = xdr_inline_decode(xdr, length); 200 - if (unlikely(p == NULL)) 195 + if (length > (3 + NGROUPS_MAX) * sizeof(u32)) 201 196 return -ENOSPC; 202 197 203 - q = p; 204 - end = q + length; 205 - 206 198 /* uid */ 207 - err = get_s32(&q, end, &tmp); 199 + err = get_host_u32(xdr, &tmp); 208 200 if (err) 209 201 return err; 210 202 creds->cr_uid = make_kuid(&init_user_ns, tmp); 211 203 212 204 /* gid */ 213 - err = get_s32(&q, end, &tmp); 205 + err = get_host_u32(xdr, &tmp); 214 206 if (err) 215 207 return err; 216 208 creds->cr_gid = make_kgid(&init_user_ns, tmp); 217 209 218 210 /* number of additional gid's */ 219 - err = get_s32(&q, end, &tmp); 211 + err = get_host_u32(xdr, &tmp); 220 212 if (err) 221 213 return err; 222 214 N = tmp; 215 + if ((3 + N) * sizeof(u32) != length) 216 + return -EINVAL; 223 217 creds->cr_group_info = groups_alloc(N); 224 218 if (creds->cr_group_info == NULL) 225 219 return -ENOMEM; ··· 222 226 /* gid's */ 223 227 for (i = 0; i < N; i++) { 224 228 kgid_t kgid; 225 - err = get_s32(&q, end, &tmp); 229 + err = get_host_u32(xdr, &tmp); 226 230 if (err) 227 231 goto out_free_groups; 228 232 err = -EINVAL; ··· 780 784 /* arg->options */ 781 785 err = dummy_enc_opt_array(xdr, &arg->options); 782 786 787 + xdr_inline_pages(&req->rq_rcv_buf, 788 + PAGE_SIZE/2 /* pretty arbitrary */, 789 + arg->pages, 0 /* page base */, arg->npages * PAGE_SIZE); 783 790 done: 784 791 if (err) 785 792 dprintk("RPC: gssx_enc_accept_sec_context: %d\n", err);
+4 -1
net/sunrpc/auth_gss/gss_rpc_xdr.h
··· 147 147 struct gssx_cb *input_cb; 148 148 u32 ret_deleg_cred; 149 149 struct gssx_option_array options; 150 + struct page **pages; 151 + unsigned int npages; 150 152 }; 151 153 152 154 struct gssx_res_accept_sec_context { ··· 242 240 2 * GSSX_max_princ_sz + \ 243 241 8 + 8 + 4 + 4 + 4) 244 242 #define GSSX_max_output_token_sz 1024 245 - #define GSSX_max_creds_sz (4 + 4 + 4 + NGROUPS_MAX * 4) 243 + /* grouplist not included; we allocate separate pages for that: */ 244 + #define GSSX_max_creds_sz (4 + 4 + 4 /* + NGROUPS_MAX*4 */) 246 245 #define GSSX_RES_accept_sec_context_sz (GSSX_default_status_sz + \ 247 246 GSSX_default_ctx_sz + \ 248 247 GSSX_max_output_token_sz + \