forked from mirrors/linux
		
	dev/parport: fix the array out-of-bounds risk
Fixed array out-of-bounds issues caused by sprintf by replacing it with snprintf for safer data copying, ensuring the destination buffer is not overflowed. Below is the stack trace I encountered during the actual issue: [ 66.575408s] [pid:5118,cpu4,QThread,4]Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: do_hardware_base_addr+0xcc/0xd0 [parport] [ 66.575408s] [pid:5118,cpu4,QThread,5]CPU: 4 PID: 5118 Comm: QThread Tainted: G S W O 5.10.97-arm64-desktop #7100.57021.2 [ 66.575439s] [pid:5118,cpu4,QThread,6]TGID: 5087 Comm: EFileApp [ 66.575439s] [pid:5118,cpu4,QThread,7]Hardware name: HUAWEI HUAWEI QingYun PGUX-W515x-B081/SP1PANGUXM, BIOS 1.00.07 04/29/2024 [ 66.575439s] [pid:5118,cpu4,QThread,8]Call trace: [ 66.575469s] [pid:5118,cpu4,QThread,9] dump_backtrace+0x0/0x1c0 [ 66.575469s] [pid:5118,cpu4,QThread,0] show_stack+0x14/0x20 [ 66.575469s] [pid:5118,cpu4,QThread,1] dump_stack+0xd4/0x10c [ 66.575500s] [pid:5118,cpu4,QThread,2] panic+0x1d8/0x3bc [ 66.575500s] [pid:5118,cpu4,QThread,3] __stack_chk_fail+0x2c/0x38 [ 66.575500s] [pid:5118,cpu4,QThread,4] do_hardware_base_addr+0xcc/0xd0 [parport] Signed-off-by: tuhaowen <tuhaowen@uniontech.com> Cc: stable <stable@kernel.org> Link: https://lore.kernel.org/r/20240708080430.8221-1-tuhaowen@uniontech.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
							parent
							
								
									feb1f0cba1
								
							
						
					
					
						commit
						ab11dac93d
					
				
					 1 changed files with 12 additions and 12 deletions
				
			
		| 
						 | 
					@ -51,12 +51,12 @@ static int do_active_device(struct ctl_table *table, int write,
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	for (dev = port->devices; dev ; dev = dev->next) {
 | 
						for (dev = port->devices; dev ; dev = dev->next) {
 | 
				
			||||||
		if(dev == port->cad) {
 | 
							if(dev == port->cad) {
 | 
				
			||||||
			len += sprintf(buffer, "%s\n", dev->name);
 | 
								len += snprintf(buffer, sizeof(buffer), "%s\n", dev->name);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(!len) {
 | 
						if(!len) {
 | 
				
			||||||
		len += sprintf(buffer, "%s\n", "none");
 | 
							len += snprintf(buffer, sizeof(buffer), "%s\n", "none");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (len > *lenp)
 | 
						if (len > *lenp)
 | 
				
			||||||
| 
						 | 
					@ -87,19 +87,19 @@ static int do_autoprobe(struct ctl_table *table, int write,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	if ((str = info->class_name) != NULL)
 | 
						if ((str = info->class_name) != NULL)
 | 
				
			||||||
		len += sprintf (buffer + len, "CLASS:%s;\n", str);
 | 
							len += snprintf (buffer + len, sizeof(buffer) - len, "CLASS:%s;\n", str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((str = info->model) != NULL)
 | 
						if ((str = info->model) != NULL)
 | 
				
			||||||
		len += sprintf (buffer + len, "MODEL:%s;\n", str);
 | 
							len += snprintf (buffer + len, sizeof(buffer) - len, "MODEL:%s;\n", str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((str = info->mfr) != NULL)
 | 
						if ((str = info->mfr) != NULL)
 | 
				
			||||||
		len += sprintf (buffer + len, "MANUFACTURER:%s;\n", str);
 | 
							len += snprintf (buffer + len, sizeof(buffer) - len, "MANUFACTURER:%s;\n", str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((str = info->description) != NULL)
 | 
						if ((str = info->description) != NULL)
 | 
				
			||||||
		len += sprintf (buffer + len, "DESCRIPTION:%s;\n", str);
 | 
							len += snprintf (buffer + len, sizeof(buffer) - len, "DESCRIPTION:%s;\n", str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((str = info->cmdset) != NULL)
 | 
						if ((str = info->cmdset) != NULL)
 | 
				
			||||||
		len += sprintf (buffer + len, "COMMAND SET:%s;\n", str);
 | 
							len += snprintf (buffer + len, sizeof(buffer) - len, "COMMAND SET:%s;\n", str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (len > *lenp)
 | 
						if (len > *lenp)
 | 
				
			||||||
		len = *lenp;
 | 
							len = *lenp;
 | 
				
			||||||
| 
						 | 
					@ -117,7 +117,7 @@ static int do_hardware_base_addr(struct ctl_table *table, int write,
 | 
				
			||||||
				 void *result, size_t *lenp, loff_t *ppos)
 | 
									 void *result, size_t *lenp, loff_t *ppos)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct parport *port = (struct parport *)table->extra1;
 | 
						struct parport *port = (struct parport *)table->extra1;
 | 
				
			||||||
	char buffer[20];
 | 
						char buffer[64];
 | 
				
			||||||
	int len = 0;
 | 
						int len = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (*ppos) {
 | 
						if (*ppos) {
 | 
				
			||||||
| 
						 | 
					@ -128,7 +128,7 @@ static int do_hardware_base_addr(struct ctl_table *table, int write,
 | 
				
			||||||
	if (write) /* permissions prevent this anyway */
 | 
						if (write) /* permissions prevent this anyway */
 | 
				
			||||||
		return -EACCES;
 | 
							return -EACCES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	len += sprintf (buffer, "%lu\t%lu\n", port->base, port->base_hi);
 | 
						len += snprintf (buffer, sizeof(buffer), "%lu\t%lu\n", port->base, port->base_hi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (len > *lenp)
 | 
						if (len > *lenp)
 | 
				
			||||||
		len = *lenp;
 | 
							len = *lenp;
 | 
				
			||||||
| 
						 | 
					@ -155,7 +155,7 @@ static int do_hardware_irq(struct ctl_table *table, int write,
 | 
				
			||||||
	if (write) /* permissions prevent this anyway */
 | 
						if (write) /* permissions prevent this anyway */
 | 
				
			||||||
		return -EACCES;
 | 
							return -EACCES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	len += sprintf (buffer, "%d\n", port->irq);
 | 
						len += snprintf (buffer, sizeof(buffer), "%d\n", port->irq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (len > *lenp)
 | 
						if (len > *lenp)
 | 
				
			||||||
		len = *lenp;
 | 
							len = *lenp;
 | 
				
			||||||
| 
						 | 
					@ -182,7 +182,7 @@ static int do_hardware_dma(struct ctl_table *table, int write,
 | 
				
			||||||
	if (write) /* permissions prevent this anyway */
 | 
						if (write) /* permissions prevent this anyway */
 | 
				
			||||||
		return -EACCES;
 | 
							return -EACCES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	len += sprintf (buffer, "%d\n", port->dma);
 | 
						len += snprintf (buffer, sizeof(buffer), "%d\n", port->dma);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (len > *lenp)
 | 
						if (len > *lenp)
 | 
				
			||||||
		len = *lenp;
 | 
							len = *lenp;
 | 
				
			||||||
| 
						 | 
					@ -213,7 +213,7 @@ static int do_hardware_modes(struct ctl_table *table, int write,
 | 
				
			||||||
#define printmode(x)							\
 | 
					#define printmode(x)							\
 | 
				
			||||||
do {									\
 | 
					do {									\
 | 
				
			||||||
	if (port->modes & PARPORT_MODE_##x)				\
 | 
						if (port->modes & PARPORT_MODE_##x)				\
 | 
				
			||||||
		len += sprintf(buffer + len, "%s%s", f++ ? "," : "", #x); \
 | 
							len += snprintf(buffer + len, sizeof(buffer) - len, "%s%s", f++ ? "," : "", #x); \
 | 
				
			||||||
} while (0)
 | 
					} while (0)
 | 
				
			||||||
		int f = 0;
 | 
							int f = 0;
 | 
				
			||||||
		printmode(PCSPP);
 | 
							printmode(PCSPP);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue