Contents of /trunk/kernel26-magellan/patches-2.6.25-r5/0116-2.6.25.17-all-fixes.patch
Parent Directory | Revision Log
Revision 677 -
(show annotations)
(download)
Wed Sep 10 21:27:27 2008 UTC (16 years ago) by niro
File size: 22098 byte(s)
Wed Sep 10 21:27:27 2008 UTC (16 years ago) by niro
File size: 22098 byte(s)
2.6.25-magellan-r5: - updated to linux-2.6.25.17
1 | diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c |
2 | index 3e18db4..f49c970 100644 |
3 | --- a/arch/x86/kernel/cpu/mtrr/generic.c |
4 | +++ b/arch/x86/kernel/cpu/mtrr/generic.c |
5 | @@ -229,6 +229,7 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base, |
6 | unsigned long *size, mtrr_type *type) |
7 | { |
8 | unsigned int mask_lo, mask_hi, base_lo, base_hi; |
9 | + unsigned int tmp, hi; |
10 | |
11 | rdmsr(MTRRphysMask_MSR(reg), mask_lo, mask_hi); |
12 | if ((mask_lo & 0x800) == 0) { |
13 | @@ -242,8 +243,18 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base, |
14 | rdmsr(MTRRphysBase_MSR(reg), base_lo, base_hi); |
15 | |
16 | /* Work out the shifted address mask. */ |
17 | - mask_lo = size_or_mask | mask_hi << (32 - PAGE_SHIFT) |
18 | - | mask_lo >> PAGE_SHIFT; |
19 | + tmp = mask_hi << (32 - PAGE_SHIFT) | mask_lo >> PAGE_SHIFT; |
20 | + mask_lo = size_or_mask | tmp; |
21 | + /* Expand tmp with high bits to all 1s*/ |
22 | + hi = fls(tmp); |
23 | + if (hi > 0) { |
24 | + tmp |= ~((1<<(hi - 1)) - 1); |
25 | + |
26 | + if (tmp != mask_lo) { |
27 | + WARN_ON("mtrr: your BIOS has set up an incorrect mask, fixing it up.\n"); |
28 | + mask_lo = tmp; |
29 | + } |
30 | + } |
31 | |
32 | /* This works correctly if size is a power of two, i.e. a |
33 | contiguous range. */ |
34 | diff --git a/crypto/authenc.c b/crypto/authenc.c |
35 | index 4b22676..fd9f06c 100644 |
36 | --- a/crypto/authenc.c |
37 | +++ b/crypto/authenc.c |
38 | @@ -174,8 +174,9 @@ static int crypto_authenc_genicv(struct aead_request *req, u8 *iv, |
39 | static void crypto_authenc_encrypt_done(struct crypto_async_request *req, |
40 | int err) |
41 | { |
42 | + struct aead_request *areq = req->data; |
43 | + |
44 | if (!err) { |
45 | - struct aead_request *areq = req->data; |
46 | struct crypto_aead *authenc = crypto_aead_reqtfm(areq); |
47 | struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); |
48 | struct ablkcipher_request *abreq = aead_request_ctx(areq); |
49 | @@ -185,7 +186,7 @@ static void crypto_authenc_encrypt_done(struct crypto_async_request *req, |
50 | err = crypto_authenc_genicv(areq, iv, 0); |
51 | } |
52 | |
53 | - aead_request_complete(req->data, err); |
54 | + aead_request_complete(areq, err); |
55 | } |
56 | |
57 | static int crypto_authenc_encrypt(struct aead_request *req) |
58 | @@ -216,14 +217,15 @@ static int crypto_authenc_encrypt(struct aead_request *req) |
59 | static void crypto_authenc_givencrypt_done(struct crypto_async_request *req, |
60 | int err) |
61 | { |
62 | + struct aead_request *areq = req->data; |
63 | + |
64 | if (!err) { |
65 | - struct aead_request *areq = req->data; |
66 | struct skcipher_givcrypt_request *greq = aead_request_ctx(areq); |
67 | |
68 | err = crypto_authenc_genicv(areq, greq->giv, 0); |
69 | } |
70 | |
71 | - aead_request_complete(req->data, err); |
72 | + aead_request_complete(areq, err); |
73 | } |
74 | |
75 | static int crypto_authenc_givencrypt(struct aead_givcrypt_request *req) |
76 | diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c |
77 | index 8e877e7..5435970 100644 |
78 | --- a/drivers/net/forcedeth.c |
79 | +++ b/drivers/net/forcedeth.c |
80 | @@ -5249,7 +5249,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i |
81 | if (id->driver_data & DEV_HAS_CHECKSUM) { |
82 | np->rx_csum = 1; |
83 | np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK; |
84 | - dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG; |
85 | + dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; |
86 | dev->features |= NETIF_F_TSO; |
87 | } |
88 | |
89 | @@ -5548,7 +5548,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i |
90 | |
91 | dev_printk(KERN_INFO, &pci_dev->dev, "%s%s%s%s%s%s%s%s%s%sdesc-v%u\n", |
92 | dev->features & NETIF_F_HIGHDMA ? "highdma " : "", |
93 | - dev->features & (NETIF_F_HW_CSUM | NETIF_F_SG) ? |
94 | + dev->features & (NETIF_F_IP_CSUM | NETIF_F_SG) ? |
95 | "csum " : "", |
96 | dev->features & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX) ? |
97 | "vlan " : "", |
98 | diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c |
99 | index 42d7c0a..0e4eb15 100644 |
100 | --- a/drivers/net/r8169.c |
101 | +++ b/drivers/net/r8169.c |
102 | @@ -2822,7 +2822,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev, |
103 | pkt_size, PCI_DMA_FROMDEVICE); |
104 | rtl8169_mark_to_asic(desc, tp->rx_buf_sz); |
105 | } else { |
106 | - pci_unmap_single(pdev, addr, pkt_size, |
107 | + pci_unmap_single(pdev, addr, tp->rx_buf_sz, |
108 | PCI_DMA_FROMDEVICE); |
109 | tp->Rx_skbuff[entry] = NULL; |
110 | } |
111 | diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c |
112 | index d8160fa..9c2b7b4 100644 |
113 | --- a/drivers/usb/class/cdc-acm.c |
114 | +++ b/drivers/usb/class/cdc-acm.c |
115 | @@ -531,8 +531,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) |
116 | tasklet_schedule(&acm->urb_task); |
117 | |
118 | done: |
119 | -err_out: |
120 | mutex_unlock(&acm->mutex); |
121 | +err_out: |
122 | mutex_unlock(&open_mutex); |
123 | return rv; |
124 | |
125 | diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c |
126 | index 59df132..4835bdc 100644 |
127 | --- a/drivers/video/fb_defio.c |
128 | +++ b/drivers/video/fb_defio.c |
129 | @@ -114,6 +114,17 @@ static struct vm_operations_struct fb_deferred_io_vm_ops = { |
130 | .page_mkwrite = fb_deferred_io_mkwrite, |
131 | }; |
132 | |
133 | +static int fb_deferred_io_set_page_dirty(struct page *page) |
134 | +{ |
135 | + if (!PageDirty(page)) |
136 | + SetPageDirty(page); |
137 | + return 0; |
138 | +} |
139 | + |
140 | +static const struct address_space_operations fb_deferred_io_aops = { |
141 | + .set_page_dirty = fb_deferred_io_set_page_dirty, |
142 | +}; |
143 | + |
144 | static int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma) |
145 | { |
146 | vma->vm_ops = &fb_deferred_io_vm_ops; |
147 | @@ -163,6 +174,14 @@ void fb_deferred_io_init(struct fb_info *info) |
148 | } |
149 | EXPORT_SYMBOL_GPL(fb_deferred_io_init); |
150 | |
151 | +void fb_deferred_io_open(struct fb_info *info, |
152 | + struct inode *inode, |
153 | + struct file *file) |
154 | +{ |
155 | + file->f_mapping->a_ops = &fb_deferred_io_aops; |
156 | +} |
157 | +EXPORT_SYMBOL_GPL(fb_deferred_io_open); |
158 | + |
159 | void fb_deferred_io_cleanup(struct fb_info *info) |
160 | { |
161 | void *screen_base = (void __force *) info->screen_base; |
162 | diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c |
163 | index 01072f4..79b410c 100644 |
164 | --- a/drivers/video/fbmem.c |
165 | +++ b/drivers/video/fbmem.c |
166 | @@ -1315,6 +1315,10 @@ fb_open(struct inode *inode, struct file *file) |
167 | if (res) |
168 | module_put(info->fbops->owner); |
169 | } |
170 | +#ifdef CONFIG_FB_DEFERRED_IO |
171 | + if (info->fbdefio) |
172 | + fb_deferred_io_open(info, inode, file); |
173 | +#endif |
174 | return res; |
175 | } |
176 | |
177 | diff --git a/fs/cifs/file.c b/fs/cifs/file.c |
178 | index 40b6900..a80a917 100644 |
179 | --- a/fs/cifs/file.c |
180 | +++ b/fs/cifs/file.c |
181 | @@ -835,6 +835,10 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, |
182 | return -EBADF; |
183 | open_file = (struct cifsFileInfo *) file->private_data; |
184 | |
185 | + rc = generic_write_checks(file, poffset, &write_size, 0); |
186 | + if (rc) |
187 | + return rc; |
188 | + |
189 | xid = GetXid(); |
190 | |
191 | if (*poffset > file->f_path.dentry->d_inode->i_size) |
192 | diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c |
193 | index 350680f..b392002 100644 |
194 | --- a/fs/cramfs/inode.c |
195 | +++ b/fs/cramfs/inode.c |
196 | @@ -44,58 +44,13 @@ static DEFINE_MUTEX(read_mutex); |
197 | static int cramfs_iget5_test(struct inode *inode, void *opaque) |
198 | { |
199 | struct cramfs_inode *cramfs_inode = opaque; |
200 | - |
201 | - if (inode->i_ino != CRAMINO(cramfs_inode)) |
202 | - return 0; /* does not match */ |
203 | - |
204 | - if (inode->i_ino != 1) |
205 | - return 1; |
206 | - |
207 | - /* all empty directories, char, block, pipe, and sock, share inode #1 */ |
208 | - |
209 | - if ((inode->i_mode != cramfs_inode->mode) || |
210 | - (inode->i_gid != cramfs_inode->gid) || |
211 | - (inode->i_uid != cramfs_inode->uid)) |
212 | - return 0; /* does not match */ |
213 | - |
214 | - if ((S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) && |
215 | - (inode->i_rdev != old_decode_dev(cramfs_inode->size))) |
216 | - return 0; /* does not match */ |
217 | - |
218 | - return 1; /* matches */ |
219 | + return inode->i_ino == CRAMINO(cramfs_inode) && inode->i_ino != 1; |
220 | } |
221 | |
222 | static int cramfs_iget5_set(struct inode *inode, void *opaque) |
223 | { |
224 | - static struct timespec zerotime; |
225 | struct cramfs_inode *cramfs_inode = opaque; |
226 | - inode->i_mode = cramfs_inode->mode; |
227 | - inode->i_uid = cramfs_inode->uid; |
228 | - inode->i_size = cramfs_inode->size; |
229 | - inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1; |
230 | - inode->i_gid = cramfs_inode->gid; |
231 | - /* Struct copy intentional */ |
232 | - inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime; |
233 | inode->i_ino = CRAMINO(cramfs_inode); |
234 | - /* inode->i_nlink is left 1 - arguably wrong for directories, |
235 | - but it's the best we can do without reading the directory |
236 | - contents. 1 yields the right result in GNU find, even |
237 | - without -noleaf option. */ |
238 | - if (S_ISREG(inode->i_mode)) { |
239 | - inode->i_fop = &generic_ro_fops; |
240 | - inode->i_data.a_ops = &cramfs_aops; |
241 | - } else if (S_ISDIR(inode->i_mode)) { |
242 | - inode->i_op = &cramfs_dir_inode_operations; |
243 | - inode->i_fop = &cramfs_directory_operations; |
244 | - } else if (S_ISLNK(inode->i_mode)) { |
245 | - inode->i_op = &page_symlink_inode_operations; |
246 | - inode->i_data.a_ops = &cramfs_aops; |
247 | - } else { |
248 | - inode->i_size = 0; |
249 | - inode->i_blocks = 0; |
250 | - init_special_inode(inode, inode->i_mode, |
251 | - old_decode_dev(cramfs_inode->size)); |
252 | - } |
253 | return 0; |
254 | } |
255 | |
256 | @@ -105,12 +60,48 @@ static struct inode *get_cramfs_inode(struct super_block *sb, |
257 | struct inode *inode = iget5_locked(sb, CRAMINO(cramfs_inode), |
258 | cramfs_iget5_test, cramfs_iget5_set, |
259 | cramfs_inode); |
260 | + static struct timespec zerotime; |
261 | + |
262 | if (inode && (inode->i_state & I_NEW)) { |
263 | + inode->i_mode = cramfs_inode->mode; |
264 | + inode->i_uid = cramfs_inode->uid; |
265 | + inode->i_size = cramfs_inode->size; |
266 | + inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1; |
267 | + inode->i_gid = cramfs_inode->gid; |
268 | + /* Struct copy intentional */ |
269 | + inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime; |
270 | + /* inode->i_nlink is left 1 - arguably wrong for directories, |
271 | + but it's the best we can do without reading the directory |
272 | + contents. 1 yields the right result in GNU find, even |
273 | + without -noleaf option. */ |
274 | + if (S_ISREG(inode->i_mode)) { |
275 | + inode->i_fop = &generic_ro_fops; |
276 | + inode->i_data.a_ops = &cramfs_aops; |
277 | + } else if (S_ISDIR(inode->i_mode)) { |
278 | + inode->i_op = &cramfs_dir_inode_operations; |
279 | + inode->i_fop = &cramfs_directory_operations; |
280 | + } else if (S_ISLNK(inode->i_mode)) { |
281 | + inode->i_op = &page_symlink_inode_operations; |
282 | + inode->i_data.a_ops = &cramfs_aops; |
283 | + } else { |
284 | + inode->i_size = 0; |
285 | + inode->i_blocks = 0; |
286 | + init_special_inode(inode, inode->i_mode, |
287 | + old_decode_dev(cramfs_inode->size)); |
288 | + } |
289 | unlock_new_inode(inode); |
290 | } |
291 | return inode; |
292 | } |
293 | |
294 | +static void cramfs_drop_inode(struct inode *inode) |
295 | +{ |
296 | + if (inode->i_ino == 1) |
297 | + generic_delete_inode(inode); |
298 | + else |
299 | + generic_drop_inode(inode); |
300 | +} |
301 | + |
302 | /* |
303 | * We have our own block cache: don't fill up the buffer cache |
304 | * with the rom-image, because the way the filesystem is set |
305 | @@ -535,6 +526,7 @@ static const struct super_operations cramfs_ops = { |
306 | .put_super = cramfs_put_super, |
307 | .remount_fs = cramfs_remount, |
308 | .statfs = cramfs_statfs, |
309 | + .drop_inode = cramfs_drop_inode, |
310 | }; |
311 | |
312 | static int cramfs_get_sb(struct file_system_type *fs_type, |
313 | diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c |
314 | index b6ed383..54b8b41 100644 |
315 | --- a/fs/nfsd/nfs4acl.c |
316 | +++ b/fs/nfsd/nfs4acl.c |
317 | @@ -443,7 +443,7 @@ init_state(struct posix_acl_state *state, int cnt) |
318 | * enough space for either: |
319 | */ |
320 | alloc = sizeof(struct posix_ace_state_array) |
321 | - + cnt*sizeof(struct posix_ace_state); |
322 | + + cnt*sizeof(struct posix_user_ace_state); |
323 | state->users = kzalloc(alloc, GFP_KERNEL); |
324 | if (!state->users) |
325 | return -ENOMEM; |
326 | diff --git a/include/linux/fb.h b/include/linux/fb.h |
327 | index 58c57a3..e1ee345 100644 |
328 | --- a/include/linux/fb.h |
329 | +++ b/include/linux/fb.h |
330 | @@ -966,6 +966,9 @@ static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, |
331 | |
332 | /* drivers/video/fb_defio.c */ |
333 | extern void fb_deferred_io_init(struct fb_info *info); |
334 | +extern void fb_deferred_io_open(struct fb_info *info, |
335 | + struct inode *inode, |
336 | + struct file *file); |
337 | extern void fb_deferred_io_cleanup(struct fb_info *info); |
338 | extern int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, |
339 | int datasync); |
340 | diff --git a/mm/page_alloc.c b/mm/page_alloc.c |
341 | index f7082af..15ff806 100644 |
342 | --- a/mm/page_alloc.c |
343 | +++ b/mm/page_alloc.c |
344 | @@ -717,6 +717,9 @@ int move_freepages(struct zone *zone, |
345 | #endif |
346 | |
347 | for (page = start_page; page <= end_page;) { |
348 | + /* Make sure we are not inadvertently changing nodes */ |
349 | + VM_BUG_ON(page_to_nid(page) != zone_to_nid(zone)); |
350 | + |
351 | if (!pfn_valid_within(page_to_pfn(page))) { |
352 | page++; |
353 | continue; |
354 | @@ -2476,6 +2479,10 @@ static void setup_zone_migrate_reserve(struct zone *zone) |
355 | continue; |
356 | page = pfn_to_page(pfn); |
357 | |
358 | + /* Watch out for overlapping nodes */ |
359 | + if (page_to_nid(page) != zone_to_nid(zone)) |
360 | + continue; |
361 | + |
362 | /* Blocks with reserved pages will never free, skip them. */ |
363 | if (PageReserved(page)) |
364 | continue; |
365 | diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c |
366 | index 4aa2b45..d11f8d6 100644 |
367 | --- a/net/sched/sch_prio.c |
368 | +++ b/net/sched/sch_prio.c |
369 | @@ -228,14 +228,20 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt) |
370 | { |
371 | struct prio_sched_data *q = qdisc_priv(sch); |
372 | struct tc_prio_qopt *qopt; |
373 | - struct nlattr *tb[TCA_PRIO_MAX + 1]; |
374 | + struct nlattr *tb[TCA_PRIO_MAX + 1] = {0}; |
375 | int err; |
376 | int i; |
377 | |
378 | - err = nla_parse_nested_compat(tb, TCA_PRIO_MAX, opt, NULL, qopt, |
379 | - sizeof(*qopt)); |
380 | - if (err < 0) |
381 | - return err; |
382 | + qopt = nla_data(opt); |
383 | + if (nla_len(opt) < sizeof(*qopt)) |
384 | + return -1; |
385 | + |
386 | + if (nla_len(opt) >= sizeof(*qopt) + sizeof(struct nlattr)) { |
387 | + err = nla_parse_nested(tb, TCA_PRIO_MAX, |
388 | + (struct nlattr *) (qopt + 1), NULL); |
389 | + if (err < 0) |
390 | + return err; |
391 | + } |
392 | |
393 | q->bands = qopt->bands; |
394 | /* If we're multiqueue, make sure the number of incoming bands |
395 | diff --git a/net/sctp/auth.c b/net/sctp/auth.c |
396 | index 675a5c3..52db5f6 100644 |
397 | --- a/net/sctp/auth.c |
398 | +++ b/net/sctp/auth.c |
399 | @@ -80,6 +80,10 @@ static struct sctp_auth_bytes *sctp_auth_create_key(__u32 key_len, gfp_t gfp) |
400 | { |
401 | struct sctp_auth_bytes *key; |
402 | |
403 | + /* Verify that we are not going to overflow INT_MAX */ |
404 | + if ((INT_MAX - key_len) < sizeof(struct sctp_auth_bytes)) |
405 | + return NULL; |
406 | + |
407 | /* Allocate the shared key */ |
408 | key = kmalloc(sizeof(struct sctp_auth_bytes) + key_len, gfp); |
409 | if (!key) |
410 | @@ -782,6 +786,9 @@ int sctp_auth_ep_set_hmacs(struct sctp_endpoint *ep, |
411 | for (i = 0; i < hmacs->shmac_num_idents; i++) { |
412 | id = hmacs->shmac_idents[i]; |
413 | |
414 | + if (id > SCTP_AUTH_HMAC_ID_MAX) |
415 | + return -EOPNOTSUPP; |
416 | + |
417 | if (SCTP_AUTH_HMAC_ID_SHA1 == id) |
418 | has_sha1 = 1; |
419 | |
420 | diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c |
421 | index e39a0cd..4c8d9f4 100644 |
422 | --- a/net/sctp/endpointola.c |
423 | +++ b/net/sctp/endpointola.c |
424 | @@ -103,6 +103,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, |
425 | |
426 | /* Initialize the CHUNKS parameter */ |
427 | auth_chunks->param_hdr.type = SCTP_PARAM_CHUNKS; |
428 | + auth_chunks->param_hdr.length = htons(sizeof(sctp_paramhdr_t)); |
429 | |
430 | /* If the Add-IP functionality is enabled, we must |
431 | * authenticate, ASCONF and ASCONF-ACK chunks |
432 | @@ -110,8 +111,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, |
433 | if (sctp_addip_enable) { |
434 | auth_chunks->chunks[0] = SCTP_CID_ASCONF; |
435 | auth_chunks->chunks[1] = SCTP_CID_ASCONF_ACK; |
436 | - auth_chunks->param_hdr.length = |
437 | - htons(sizeof(sctp_paramhdr_t) + 2); |
438 | + auth_chunks->param_hdr.length += htons(2); |
439 | } |
440 | } |
441 | |
442 | diff --git a/net/sctp/socket.c b/net/sctp/socket.c |
443 | index 2d42260..f8c66d6 100644 |
444 | --- a/net/sctp/socket.c |
445 | +++ b/net/sctp/socket.c |
446 | @@ -2983,6 +2983,9 @@ static int sctp_setsockopt_auth_chunk(struct sock *sk, |
447 | { |
448 | struct sctp_authchunk val; |
449 | |
450 | + if (!sctp_auth_enable) |
451 | + return -EACCES; |
452 | + |
453 | if (optlen != sizeof(struct sctp_authchunk)) |
454 | return -EINVAL; |
455 | if (copy_from_user(&val, optval, optlen)) |
456 | @@ -3011,8 +3014,12 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk, |
457 | int optlen) |
458 | { |
459 | struct sctp_hmacalgo *hmacs; |
460 | + u32 idents; |
461 | int err; |
462 | |
463 | + if (!sctp_auth_enable) |
464 | + return -EACCES; |
465 | + |
466 | if (optlen < sizeof(struct sctp_hmacalgo)) |
467 | return -EINVAL; |
468 | |
469 | @@ -3025,8 +3032,9 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk, |
470 | goto out; |
471 | } |
472 | |
473 | - if (hmacs->shmac_num_idents == 0 || |
474 | - hmacs->shmac_num_idents > SCTP_AUTH_NUM_HMACS) { |
475 | + idents = hmacs->shmac_num_idents; |
476 | + if (idents == 0 || idents > SCTP_AUTH_NUM_HMACS || |
477 | + (idents * sizeof(u16)) > (optlen - sizeof(struct sctp_hmacalgo))) { |
478 | err = -EINVAL; |
479 | goto out; |
480 | } |
481 | @@ -3051,6 +3059,9 @@ static int sctp_setsockopt_auth_key(struct sock *sk, |
482 | struct sctp_association *asoc; |
483 | int ret; |
484 | |
485 | + if (!sctp_auth_enable) |
486 | + return -EACCES; |
487 | + |
488 | if (optlen <= sizeof(struct sctp_authkey)) |
489 | return -EINVAL; |
490 | |
491 | @@ -3063,6 +3074,11 @@ static int sctp_setsockopt_auth_key(struct sock *sk, |
492 | goto out; |
493 | } |
494 | |
495 | + if (authkey->sca_keylength > optlen - sizeof(struct sctp_authkey)) { |
496 | + ret = -EINVAL; |
497 | + goto out; |
498 | + } |
499 | + |
500 | asoc = sctp_id2assoc(sk, authkey->sca_assoc_id); |
501 | if (!asoc && authkey->sca_assoc_id && sctp_style(sk, UDP)) { |
502 | ret = -EINVAL; |
503 | @@ -3088,6 +3104,9 @@ static int sctp_setsockopt_active_key(struct sock *sk, |
504 | struct sctp_authkeyid val; |
505 | struct sctp_association *asoc; |
506 | |
507 | + if (!sctp_auth_enable) |
508 | + return -EACCES; |
509 | + |
510 | if (optlen != sizeof(struct sctp_authkeyid)) |
511 | return -EINVAL; |
512 | if (copy_from_user(&val, optval, optlen)) |
513 | @@ -3113,6 +3132,9 @@ static int sctp_setsockopt_del_key(struct sock *sk, |
514 | struct sctp_authkeyid val; |
515 | struct sctp_association *asoc; |
516 | |
517 | + if (!sctp_auth_enable) |
518 | + return -EACCES; |
519 | + |
520 | if (optlen != sizeof(struct sctp_authkeyid)) |
521 | return -EINVAL; |
522 | if (copy_from_user(&val, optval, optlen)) |
523 | @@ -5073,19 +5095,29 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len, |
524 | static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, |
525 | char __user *optval, int __user *optlen) |
526 | { |
527 | + struct sctp_hmacalgo __user *p = (void __user *)optval; |
528 | struct sctp_hmac_algo_param *hmacs; |
529 | - __u16 param_len; |
530 | + __u16 data_len = 0; |
531 | + u32 num_idents; |
532 | + |
533 | + if (!sctp_auth_enable) |
534 | + return -EACCES; |
535 | |
536 | hmacs = sctp_sk(sk)->ep->auth_hmacs_list; |
537 | - param_len = ntohs(hmacs->param_hdr.length); |
538 | + data_len = ntohs(hmacs->param_hdr.length) - sizeof(sctp_paramhdr_t); |
539 | |
540 | - if (len < param_len) |
541 | + if (len < sizeof(struct sctp_hmacalgo) + data_len) |
542 | return -EINVAL; |
543 | + |
544 | + len = sizeof(struct sctp_hmacalgo) + data_len; |
545 | + num_idents = data_len / sizeof(u16); |
546 | + |
547 | if (put_user(len, optlen)) |
548 | return -EFAULT; |
549 | - if (copy_to_user(optval, hmacs->hmac_ids, len)) |
550 | + if (put_user(num_idents, &p->shmac_num_idents)) |
551 | + return -EFAULT; |
552 | + if (copy_to_user(p->shmac_idents, hmacs->hmac_ids, data_len)) |
553 | return -EFAULT; |
554 | - |
555 | return 0; |
556 | } |
557 | |
558 | @@ -5095,6 +5127,9 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len, |
559 | struct sctp_authkeyid val; |
560 | struct sctp_association *asoc; |
561 | |
562 | + if (!sctp_auth_enable) |
563 | + return -EACCES; |
564 | + |
565 | if (len < sizeof(struct sctp_authkeyid)) |
566 | return -EINVAL; |
567 | if (copy_from_user(&val, optval, sizeof(struct sctp_authkeyid))) |
568 | @@ -5109,6 +5144,12 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len, |
569 | else |
570 | val.scact_keynumber = sctp_sk(sk)->ep->active_key_id; |
571 | |
572 | + len = sizeof(struct sctp_authkeyid); |
573 | + if (put_user(len, optlen)) |
574 | + return -EFAULT; |
575 | + if (copy_to_user(optval, &val, len)) |
576 | + return -EFAULT; |
577 | + |
578 | return 0; |
579 | } |
580 | |
581 | @@ -5119,13 +5160,16 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, |
582 | struct sctp_authchunks val; |
583 | struct sctp_association *asoc; |
584 | struct sctp_chunks_param *ch; |
585 | - u32 num_chunks; |
586 | + u32 num_chunks = 0; |
587 | char __user *to; |
588 | |
589 | - if (len <= sizeof(struct sctp_authchunks)) |
590 | + if (!sctp_auth_enable) |
591 | + return -EACCES; |
592 | + |
593 | + if (len < sizeof(struct sctp_authchunks)) |
594 | return -EINVAL; |
595 | |
596 | - if (copy_from_user(&val, p, sizeof(struct sctp_authchunks))) |
597 | + if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks))) |
598 | return -EFAULT; |
599 | |
600 | to = p->gauth_chunks; |
601 | @@ -5134,20 +5178,21 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, |
602 | return -EINVAL; |
603 | |
604 | ch = asoc->peer.peer_chunks; |
605 | + if (!ch) |
606 | + goto num; |
607 | |
608 | /* See if the user provided enough room for all the data */ |
609 | num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t); |
610 | if (len < num_chunks) |
611 | return -EINVAL; |
612 | |
613 | - len = num_chunks; |
614 | - if (put_user(len, optlen)) |
615 | + if (copy_to_user(to, ch->chunks, num_chunks)) |
616 | return -EFAULT; |
617 | +num: |
618 | + len = sizeof(struct sctp_authchunks) + num_chunks; |
619 | + if (put_user(len, optlen)) return -EFAULT; |
620 | if (put_user(num_chunks, &p->gauth_number_of_chunks)) |
621 | return -EFAULT; |
622 | - if (copy_to_user(to, ch->chunks, len)) |
623 | - return -EFAULT; |
624 | - |
625 | return 0; |
626 | } |
627 | |
628 | @@ -5158,13 +5203,16 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, |
629 | struct sctp_authchunks val; |
630 | struct sctp_association *asoc; |
631 | struct sctp_chunks_param *ch; |
632 | - u32 num_chunks; |
633 | + u32 num_chunks = 0; |
634 | char __user *to; |
635 | |
636 | - if (len <= sizeof(struct sctp_authchunks)) |
637 | + if (!sctp_auth_enable) |
638 | + return -EACCES; |
639 | + |
640 | + if (len < sizeof(struct sctp_authchunks)) |
641 | return -EINVAL; |
642 | |
643 | - if (copy_from_user(&val, p, sizeof(struct sctp_authchunks))) |
644 | + if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks))) |
645 | return -EFAULT; |
646 | |
647 | to = p->gauth_chunks; |
648 | @@ -5177,17 +5225,21 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, |
649 | else |
650 | ch = sctp_sk(sk)->ep->auth_chunk_list; |
651 | |
652 | + if (!ch) |
653 | + goto num; |
654 | + |
655 | num_chunks = ntohs(ch->param_hdr.length) - sizeof(sctp_paramhdr_t); |
656 | - if (len < num_chunks) |
657 | + if (len < sizeof(struct sctp_authchunks) + num_chunks) |
658 | return -EINVAL; |
659 | |
660 | - len = num_chunks; |
661 | + if (copy_to_user(to, ch->chunks, num_chunks)) |
662 | + return -EFAULT; |
663 | +num: |
664 | + len = sizeof(struct sctp_authchunks) + num_chunks; |
665 | if (put_user(len, optlen)) |
666 | return -EFAULT; |
667 | if (put_user(num_chunks, &p->gauth_number_of_chunks)) |
668 | return -EFAULT; |
669 | - if (copy_to_user(to, ch->chunks, len)) |
670 | - return -EFAULT; |
671 | |
672 | return 0; |
673 | } |
674 | diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c |
675 | index 0f8c439..5231f7a 100644 |
676 | --- a/net/sunrpc/sysctl.c |
677 | +++ b/net/sunrpc/sysctl.c |
678 | @@ -60,24 +60,14 @@ static int proc_do_xprt(ctl_table *table, int write, struct file *file, |
679 | void __user *buffer, size_t *lenp, loff_t *ppos) |
680 | { |
681 | char tmpbuf[256]; |
682 | - int len; |
683 | + size_t len; |
684 | + |
685 | if ((*ppos && !write) || !*lenp) { |
686 | *lenp = 0; |
687 | return 0; |
688 | } |
689 | - if (write) |
690 | - return -EINVAL; |
691 | - else { |
692 | - len = svc_print_xprts(tmpbuf, sizeof(tmpbuf)); |
693 | - if (!access_ok(VERIFY_WRITE, buffer, len)) |
694 | - return -EFAULT; |
695 | - |
696 | - if (__copy_to_user(buffer, tmpbuf, len)) |
697 | - return -EFAULT; |
698 | - } |
699 | - *lenp -= len; |
700 | - *ppos += len; |
701 | - return 0; |
702 | + len = svc_print_xprts(tmpbuf, sizeof(tmpbuf)); |
703 | + return simple_read_from_buffer(buffer, *lenp, ppos, tmpbuf, len); |
704 | } |
705 | |
706 | static int |