Re: [PATCH] zram: fix NULL pointer dereference in zcomp_available_show()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 25/08/05 10:43AM, Seyediman Seyedarab wrote:
> On 25/08/05 09:38AM, Seyediman Seyedarab wrote:
> > On 25/08/05 07:22PM, Sergey Senozhatsky wrote:
> > > On (25/08/03 02:25), Seyediman Seyedarab wrote:
> > > > Temporarily add a NULL check in zcomp_available_show() to prevent the
> > > > crash. The use-after-free issue requires a more comprehensive fix using
> > > > proper reference counting to ensure the zram structure isn't freed while
> > > > still in use.
> > > 
> > > Not without a reproducer, sorry.  Per my limited experience, attempts
> > > to fix syzkaller reports w/o reproducers often lead to regressions or
> > > just more problems.
> > 
> > It can be reproduced with the following code:
> > #include <stdlib.h>
> > #include <stdio.h>
> > #include <fcntl.h>
> > #include <unistd.h>
> > 
> > int main()
> > {
> >     int hot_remove_fd, comp_alg_fd, disksize_fd;
> >     char buf[256];
> >     
> >     system("modprobe -r zram");
> >     system("modprobe zram");
> >     
> >     disksize_fd = open("/sys/block/zram0/disksize", O_WRONLY);
> >     if (disksize_fd >= 0) {
> >         write(disksize_fd, "1073741824", 10);
> >         close(disksize_fd);
> >     }
> > 
> >     hot_remove_fd = open("/sys/class/zram-control/hot_remove", O_WRONLY);
> >     comp_alg_fd = open("/sys/block/zram0/comp_algorithm", O_RDONLY);
> >     
> >     write(hot_remove_fd, "0", 1);
> >     
> >     for (int i = 0; i < 1000000; i++) {
> >         lseek(comp_alg_fd, 0, SEEK_SET);
> >         read(comp_alg_fd, buf, sizeof(buf));
> >         printf("comp_algorithm: %s", buf);
> >     }
> > }
> > 
> > Which produces corrupted output sometimes. (it's a race condition, so it
> > doesn't happen all the time...)
> 
> To clarify: the reproducer I provided shows only the use-after-free 
> issue where zram structure is freed while sysfs reads are ongoing.
> 
> The NULL dereference (which syzbot reported) has a much tighter race 
> window: it requires catching the brief moment during zram_reset_device() 
> where comp_algs[prio] is NULL between zram_destroy_comps() and 
> comp_algorithm_set(). This 'can' be triggered by racing concurrent:
> - writes to /sys/block/zram0/reset 
> - reads from /sys/block/zram0/comp_algorithm
> The window is only a few instructions wide under write lock, so it is 
> significantly harder to reproduce than the use-after-free.
> 
> Your patch [1] should fixes the NULL deref, but the use-after-free remains.
> 
> [1] https://lore.kernel.org/r/20250805101946.1774112-1-senozhatsky@xxxxxxxxxxxx

I need to correct my previous statement about the use-after-free issue.

My reproducer was wrong. The garbage output I reported was actually from
an uninitialized buffer in  my test code, not from reading freed memory! 
When the device is removed, the kernel correctly returns -ENODEV
rather than accessing freed memory:

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
	int hot_remove_fd, comp_alg_fd, disksize_fd;
	ssize_t nBytes = 0;
	char buf[256] = {0};

	system("modprobe -r zram");
	system("modprobe zram");

	disksize_fd = open("/sys/block/zram0/disksize", O_WRONLY);
	if (disksize_fd >= 0) {
		write(disksize_fd, "1G", 2);
		close(disksize_fd);
	}

	hot_remove_fd = open("/sys/class/zram-control/hot_remove", O_WRONLY);
	comp_alg_fd = open("/sys/block/zram0/comp_algorithm", O_RDONLY);

	write(hot_remove_fd, "0", 1);

	for (int i = 0; i < 1000000; i++) {
		lseek(comp_alg_fd, 0, SEEK_SET);
		nBytes = read(comp_alg_fd, buf, sizeof(buf));
		if (nBytes <= 0) {
			perror("read");
			break;
		}
		printf("comp_alg: %s", buf);
	}
}

Output:
read: No such device

The kernel properly protects against use-after-free in this path. I 
apologize for the confusion.

Kindest Regards,
Seyediman





[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux