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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'nfsd-5.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux

Pull nfsd fixes from Chuck Lever:
"Notable changes:

- There is now a backup maintainer for NFSD

Notable fixes:

- Prevent array overruns in svc_rdma_build_writes()

- Prevent buffer overruns when encoding NFSv3 READDIR results

- Fix a potential UAF in nfsd_file_put()"

* tag 'nfsd-5.19-1' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux:
SUNRPC: Remove pointer type casts from xdr_get_next_encode_buffer()
SUNRPC: Clean up xdr_get_next_encode_buffer()
SUNRPC: Clean up xdr_commit_encode()
SUNRPC: Optimize xdr_reserve_space()
SUNRPC: Fix the calculation of xdr->end in xdr_get_next_encode_buffer()
SUNRPC: Trap RDMA segment overflows
NFSD: Fix potential use-after-free in nfsd_file_put()
MAINTAINERS: reciprocal co-maintainership for file locking and nfsd

+47 -21
+2
MAINTAINERS
··· 7654 7654 7655 7655 FILE LOCKING (flock() and fcntl()/lockf()) 7656 7656 M: Jeff Layton <jlayton@kernel.org> 7657 + M: Chuck Lever <chuck.lever@oracle.com> 7657 7658 L: linux-fsdevel@vger.kernel.org 7658 7659 S: Maintained 7659 7660 F: fs/fcntl.c ··· 10747 10746 10748 10747 KERNEL NFSD, SUNRPC, AND LOCKD SERVERS 10749 10748 M: Chuck Lever <chuck.lever@oracle.com> 10749 + M: Jeff Layton <jlayton@kernel.org> 10750 10750 L: linux-nfs@vger.kernel.org 10751 10751 S: Supported 10752 10752 W: http://nfs.sourceforge.net/
+5 -4
fs/nfsd/filecache.c
··· 309 309 if (test_bit(NFSD_FILE_HASHED, &nf->nf_flags) == 0) { 310 310 nfsd_file_flush(nf); 311 311 nfsd_file_put_noref(nf); 312 - } else { 312 + } else if (nf->nf_file) { 313 313 nfsd_file_put_noref(nf); 314 - if (nf->nf_file) 315 - nfsd_file_schedule_laundrette(); 316 - } 314 + nfsd_file_schedule_laundrette(); 315 + } else 316 + nfsd_file_put_noref(nf); 317 + 317 318 if (atomic_long_read(&nfsd_filecache_count) >= NFSD_FILE_LRU_LIMIT) 318 319 nfsd_file_gc(); 319 320 }
+15 -1
include/linux/sunrpc/xdr.h
··· 243 243 extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes); 244 244 extern int xdr_reserve_space_vec(struct xdr_stream *xdr, struct kvec *vec, 245 245 size_t nbytes); 246 - extern void xdr_commit_encode(struct xdr_stream *xdr); 246 + extern void __xdr_commit_encode(struct xdr_stream *xdr); 247 247 extern void xdr_truncate_encode(struct xdr_stream *xdr, size_t len); 248 248 extern int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen); 249 249 extern void xdr_write_pages(struct xdr_stream *xdr, struct page **pages, ··· 304 304 xdr_reset_scratch_buffer(struct xdr_stream *xdr) 305 305 { 306 306 xdr_set_scratch_buffer(xdr, NULL, 0); 307 + } 308 + 309 + /** 310 + * xdr_commit_encode - Ensure all data is written to xdr->buf 311 + * @xdr: pointer to xdr_stream 312 + * 313 + * Handle encoding across page boundaries by giving the caller a 314 + * temporary location to write to, then later copying the data into 315 + * place. __xdr_commit_encode() does that copying. 316 + */ 317 + static inline void xdr_commit_encode(struct xdr_stream *xdr) 318 + { 319 + if (unlikely(xdr->scratch.iov_len)) 320 + __xdr_commit_encode(xdr); 307 321 } 308 322 309 323 /**
+23 -14
net/sunrpc/xdr.c
··· 919 919 EXPORT_SYMBOL_GPL(xdr_init_encode); 920 920 921 921 /** 922 - * xdr_commit_encode - Ensure all data is written to buffer 922 + * __xdr_commit_encode - Ensure all data is written to buffer 923 923 * @xdr: pointer to xdr_stream 924 924 * 925 925 * We handle encoding across page boundaries by giving the caller a ··· 931 931 * required at the end of encoding, or any other time when the xdr_buf 932 932 * data might be read. 933 933 */ 934 - inline void xdr_commit_encode(struct xdr_stream *xdr) 934 + void __xdr_commit_encode(struct xdr_stream *xdr) 935 935 { 936 - int shift = xdr->scratch.iov_len; 936 + size_t shift = xdr->scratch.iov_len; 937 937 void *page; 938 938 939 - if (shift == 0) 940 - return; 941 939 page = page_address(*xdr->page_ptr); 942 940 memcpy(xdr->scratch.iov_base, page, shift); 943 941 memmove(page, page + shift, (void *)xdr->p - page); 944 942 xdr_reset_scratch_buffer(xdr); 945 943 } 946 - EXPORT_SYMBOL_GPL(xdr_commit_encode); 944 + EXPORT_SYMBOL_GPL(__xdr_commit_encode); 947 945 948 - static __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr, 949 - size_t nbytes) 946 + /* 947 + * The buffer space to be reserved crosses the boundary between 948 + * xdr->buf->head and xdr->buf->pages, or between two pages 949 + * in xdr->buf->pages. 950 + */ 951 + static noinline __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr, 952 + size_t nbytes) 950 953 { 951 - __be32 *p; 952 954 int space_left; 953 955 int frag1bytes, frag2bytes; 956 + void *p; 954 957 955 958 if (nbytes > PAGE_SIZE) 956 959 goto out_overflow; /* Bigger buffers require special handling */ ··· 967 964 xdr->buf->page_len += frag1bytes; 968 965 xdr->page_ptr++; 969 966 xdr->iov = NULL; 967 + 970 968 /* 971 969 * If the last encode didn't end exactly on a page boundary, the 972 970 * next one will straddle boundaries. Encode into the next ··· 976 972 * space at the end of the previous buffer: 977 973 */ 978 974 xdr_set_scratch_buffer(xdr, xdr->p, frag1bytes); 979 - p = page_address(*xdr->page_ptr); 975 + 980 976 /* 981 - * Note this is where the next encode will start after we've 982 - * shifted this one back: 977 + * xdr->p is where the next encode will start after 978 + * xdr_commit_encode() has shifted this one back: 983 979 */ 984 - xdr->p = (void *)p + frag2bytes; 980 + p = page_address(*xdr->page_ptr); 981 + xdr->p = p + frag2bytes; 985 982 space_left = xdr->buf->buflen - xdr->buf->len; 986 - xdr->end = (void *)p + min_t(int, space_left, PAGE_SIZE); 983 + if (space_left - nbytes >= PAGE_SIZE) 984 + xdr->end = p + PAGE_SIZE; 985 + else 986 + xdr->end = p + space_left - frag1bytes; 987 + 987 988 xdr->buf->page_len += frag2bytes; 988 989 xdr->buf->len += nbytes; 989 990 return p;
+2 -2
net/sunrpc/xprtrdma/svc_rdma_rw.c
··· 478 478 unsigned int write_len; 479 479 u64 offset; 480 480 481 - seg = &info->wi_chunk->ch_segments[info->wi_seg_no]; 482 - if (!seg) 481 + if (info->wi_seg_no >= info->wi_chunk->ch_segcount) 483 482 goto out_overflow; 484 483 484 + seg = &info->wi_chunk->ch_segments[info->wi_seg_no]; 485 485 write_len = min(remaining, seg->rs_length - info->wi_seg_off); 486 486 if (!write_len) 487 487 goto out_overflow;