projg2 / eclean-kernel

Installed kernel cleanup tool
GNU General Public License v2.0
31 stars 10 forks source link

ValueError: embedded null byte #27

Open Flowdalic opened 2 years ago

Flowdalic commented 2 years ago

I get ValueError: embedded null byte when running eclean-kernel version 2.99.3:

* Removing kernel 5.13.16-gentoo-dist (not referenced by bootloader (grub2))                                                                                                             
Traceback (most recent call last):                                                                        
  File "/usr/lib/python-exec/python3.9/eclean-kernel", line 33, in <module>                                                                                                              
    sys.exit(load_entry_point('eclean-kernel==2.99.3', 'console_scripts', 'eclean-kernel')())   
  File "/usr/lib/python3.9/site-packages/ecleankernel/__main__.py", line 382, in setuptools_main                                                                                         
    sys.exit(main(sys.argv[1:]))                                                                                                                                                         
  File "/usr/lib/python3.9/site-packages/ecleankernel/__main__.py", line 332, in main                                                                                                    
    p = subprocess.Popen(scmd)                                                                            
  File "/usr/lib/python3.9/subprocess.py", line 951, in __init__                                 self._execute_child(args, executable, preexec_fn, close_fds,                                                                                                                         
  File "/usr/lib/python3.9/subprocess.py", line 1754, in _execute_child                                                                                                                  
    self.pid = _posixsubprocess.fork_exec(     
ValueError: embedded null byte

Using pdb shows the null byte:

* Removing kernel 5.13.15-gentoo-dist (not referenced by bootloader (grub2))
> /usr/lib/python3.9/site-packages/ecleankernel/__main__.py(332)main()
-> p = subprocess.Popen(scmd)
(Pdb) 
 [-] /boot/vmlinuz-5.13.15-gentoo-dist
 [-] /lib/modules/5.13.15-gentoo-dist
 [-] /boot/System.map-5.13.15-gentoo-dist
 [-] /boot/config-5.13.15-gentoo-dist
* Removing kernel 5.13.15-gentoo-dist (not referenced by bootloader (grub2))
> /usr/lib/python3.9/site-packages/ecleankernel/__main__.py(332)main()-> p = subprocess.Popen(scmd)
(Pdb) p scmd
['kernel-install', 'remove', '\x00CIFS', '/boot/initramfs-5.13.15-gentoo-dist.img']
(Pdb) p kf.internal_version
'\x00CIFS'
(Pdb) p kf
KernelImage(PosixPath('/boot/initramfs-5.13.15-gentoo-dist.img'))

Maybe a bug in KernelImage.read_internal_version()?

mgorny commented 2 years ago

Looks like it. Could you try debugging it?

Flowdalic commented 9 months ago

Here is what I have so far:

This appears to only happen if eclean-kernel looks at an initramfs. Here read_version_from_raw() returns the wrong information:

> /usr/lib/python3.11/site-packages/ecleankernel/file.py(216)read_version_from_raw()
-> return sbuf
(Pdb) p sbuf
b'\x00CIFS VFS Client for Linux\x00fs/smb/client/sess.c\x00OS/2\x00CIFS: %s: OS/2 server\n\x00CIFS: %s: bleft %d\n\x00CIFS: %s: serverOS=%s\n\x00CIFS: %s: serverNOS=%s\n\x00CIFS: %s: serverDomain=%s\n\x00CIFS: %s: Guest login\n\x00CIFS: %s: UID = %llu\n\x00fs/smb/client/cifsglob.h\x00yes\x00no\x00\x00%s: ses '
(Pdb) bt
  /usr/lib/python3.11/bdb.py(600)run()
-> exec(cmd, globals, locals)
  <string>(1)<module>()
  /usr/lib/python-exec/python-exec2(98)<module>()
-> exec(data, new_globals)
  <string>(8)<module>()
  /usr/lib/python3.11/site-packages/ecleankernel/__main__.py(392)setuptools_main()
-> sys.exit(main(sys.argv[1:]))
  /usr/lib/python3.11/site-packages/ecleankernel/__main__.py(237)main()
-> kernels = layout.find_kernels(exclusions=exclusions)
  /usr/lib/python3.11/site-packages/ecleankernel/layout/std.py(94)find_kernels()
-> kobj = KernelImage(path)
  /usr/lib/python3.11/site-packages/ecleankernel/file.py(112)__init__()
-> self.internal_version = self.read_internal_version()
  /usr/lib/python3.11/site-packages/ecleankernel/file.py(163)read_internal_version()
-> verbuf = func(f)
> /usr/lib/python3.11/site-packages/ecleankernel/file.py(216)read_version_from_raw()
-> return sbuf

Looking at read_version_from_raw() in file.py the whole approach appears to be fragile and prone to false positives. Which is nicely demonstrated by this issue.