diff options
| author | Anton Blanchard <anton@samba.org> | 2011-11-27 21:14:46 +0000 | 
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2011-11-28 18:07:29 -0500 | 
| commit | 5cac98dd06bc43a7baab3523184f70fd359e9f35 (patch) | |
| tree | 454623a8d7ba16e94b97d9e3107f0ac4c43164d9 | |
| parent | c4860ba2e11261a541632ceee8267ca490d9eb98 (diff) | |
net: Fix corruption in /proc/*/net/dev_mcast
I just hit this during my testing. Isn't there another bug lurking?
BUG kmalloc-8: Redzone overwritten
INFO: 0xc0000000de9dec48-0xc0000000de9dec4b. First byte 0x0 instead of 0xcc
INFO: Allocated in .__seq_open_private+0x30/0xa0 age=0 cpu=5 pid=3896
	.__kmalloc+0x1e0/0x2d0
	.__seq_open_private+0x30/0xa0
	.seq_open_net+0x60/0xe0
	.dev_mc_seq_open+0x4c/0x70
	.proc_reg_open+0xd8/0x260
	.__dentry_open.clone.11+0x2b8/0x400
	.do_last+0xf4/0x950
	.path_openat+0xf8/0x480
	.do_filp_open+0x48/0xc0
	.do_sys_open+0x140/0x250
	syscall_exit+0x0/0x40
dev_mc_seq_ops uses dev_seq_start/next/stop but only allocates
sizeof(struct seq_net_private) of private data, whereas it expects
sizeof(struct dev_iter_state):
struct dev_iter_state {
	struct seq_net_private p;
	unsigned int pos; /* bucket << BUCKET_SPACE + offset */
};
Create dev_seq_open_ops and use it so we don't have to expose
struct dev_iter_state.
[ Problem added by commit f04565ddf52e4 (dev: use name hash for
  dev_seq_ops) -Eric ]
Signed-off-by: Anton Blanchard <anton@samba.org>
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | include/linux/netdevice.h | 2 | ||||
| -rw-r--r-- | net/core/dev.c | 6 | ||||
| -rw-r--r-- | net/core/dev_addr_lists.c | 3 | 
3 files changed, 9 insertions, 2 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index cbeb5867cff7..a82ad4dd306a 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2536,6 +2536,8 @@ extern void		net_disable_timestamp(void);  extern void *dev_seq_start(struct seq_file *seq, loff_t *pos);  extern void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos);  extern void dev_seq_stop(struct seq_file *seq, void *v); +extern int dev_seq_open_ops(struct inode *inode, struct file *file, +			    const struct seq_operations *ops);  #endif  extern int netdev_class_create_file(struct class_attribute *class_attr); diff --git a/net/core/dev.c b/net/core/dev.c index 6ba50a1e404c..1482eea0bbf0 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4282,6 +4282,12 @@ static int dev_seq_open(struct inode *inode, struct file *file)  			    sizeof(struct dev_iter_state));  } +int dev_seq_open_ops(struct inode *inode, struct file *file, +		     const struct seq_operations *ops) +{ +	return seq_open_net(inode, file, ops, sizeof(struct dev_iter_state)); +} +  static const struct file_operations dev_seq_fops = {  	.owner	 = THIS_MODULE,  	.open    = dev_seq_open, diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index 277faef9148d..febba516db62 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c @@ -696,8 +696,7 @@ static const struct seq_operations dev_mc_seq_ops = {  static int dev_mc_seq_open(struct inode *inode, struct file *file)  { -	return seq_open_net(inode, file, &dev_mc_seq_ops, -			    sizeof(struct seq_net_private)); +	return dev_seq_open_ops(inode, file, &dev_mc_seq_ops);  }  static const struct file_operations dev_mc_seq_fops = {  | 
