2

Trying to get rid of Ubuntu's apport by clearing /proc/sys/kernel/core_pattern using
sh -c ': > /proc/sys/kernel/core_pattern' does not work.

It looks like the O_TRUNC flag is ignored when writing to the /proc filesystem:

echo nonsense >| /proc/sys/kernel/core_pattern
strace sh -c ': > /proc/sys/kernel/core_pattern  # do not call apport'
...
openat(AT_FDCWD, "/proc/sys/kernel/core_pattern", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
...
close(3)                                = 0

cat /proc/sys/kernel/core_pattern
nonsense

I get an empty file when doing this in regular filesystems instead of the /proc filesystem.

Is that a kernel bug or a feature, perhaps even a documented one?

Edit: Clearing this setting through sysctl does not work:

sysctl kernel.core_pattern=""
sysctl: malformed setting "kernel.core_pattern="

It seems the sysctl program is unable to clear any kernel parameters while man core explicitly describes that an empty value is used to disable the mechanism.

Yes, echo >| /proc/sys/kernel/core_pattern works instead, but the object of this question is to find out whether this is a kernel bug, not to find a workaround.

Juergen
  • 272
  • 1
  • 11
  • Try writing a zero length buffer to the file. If that doesn't work, try writing just a single newline character. – Ian Abbott Aug 17 '21 at 16:58
  • BTW, the usual method of modifying `/proc/sys/` files is by using the `sysctl` command. E.g. `sudo sysctl kernel.core_pattern=`. – Ian Abbott Aug 17 '21 at 17:04
  • Files on /proc are a bit weird anyway because their content is generated dynamically and their sizes are listed as 0. – Ian Abbott Aug 18 '21 at 09:17
  • @IanAbbott, just edited the question to show that `sysctl` does not work here. But this is not the object of the question anyway. – Juergen Aug 19 '21 at 09:17
  • It could be argued that since the file has a size of 0 (as indicated by `stat`) then it cannot be truncated. – Ian Abbott Aug 19 '21 at 11:34
  • @IanAbbott, good point. But I'd like some source that is more than an argument for that to become the accepted answer of the question. Do you think I should ask a new question for that, e.g. "Can non-empty virtual files that appear as zero-length still be truncated" ? – Juergen Aug 19 '21 at 13:01

1 Answers1

1

This is because the O_TRUNC flag of the open* family of syscalls merely updates the size of the inode associated with the opened file. This change is performed right after finding the inode and before finalizing the struct file that is then used by the kernel for any actual operation on the opened file. Truncation is performed before the call to any ->open() file_operations handler implemented by whichever kernel module/driver/subsystem (like for example the sysctl subsystem) and is therefore transparent to the handler.

In other words, the file_operations handlers of the virtual sysctl files (e.g. /proc/sys/kernel/*) merely see a file with a 0 (zero) size (->i_size field of struct inode), they do not know whether this was the result of a truncation or a "normal" open, nor they should need such information.

Since sysctl files (just as the near totality of procfs files) do not really bother tracking sizes for understandable reasons, their functionality is only implemented in terms of read and write system calls (which also do not update the size in any way).

Indeed, using : > PATH will merely do open + close, while a simple echo > PATH will write a newline character after opening, thus you observe two different outcomes. You would observe the same behavior as : > PATH using truncate -s 0 PATH, though this time the truncation is done explicitly after opening through ftruncate (at least on my system).

man core explicitly describes that an empty value is used to disable the mechanism

[...]

Is that a kernel bug or a feature, perhaps even a documented one?

Human readable/writable files under procfs are usually designed to work in a line-oriented fashion, so I would assume that the term "empty" here simply means that the value of the option is empty as a result of writing an empty line to the file. If anything, I would call this an undocumented feature rather than a bug.


Here's some example traces on my system:

root@xxx:~# cat /proc/sys/kernel/core_pattern
|/usr/share/apport/apport %p %s %c %d %P %E
root@xxx:~# strace -f -e openat,write,close,dup2 sh -c ': > /proc/sys/kernel/core_pattern'
...
openat(AT_FDCWD, "/proc/sys/kernel/core_pattern", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
close(1)                                = 0
dup2(3, 1)                              = 1
close(3)                                = 0
...
+++ exited with 0 +++
root@xxx:~# cat /proc/sys/kernel/core_pattern
|/usr/share/apport/apport %p %s %c %d %P %E
root@xxx:~#
root@xxx:~# cat /proc/sys/kernel/core_pattern
|/usr/share/apport/apport %p %s %c %d %P %E
root@xxx:~# strace -f -e openat,write,close,dup2 sh -c 'echo > /proc/sys/kernel/core_pattern'
...
openat(AT_FDCWD, "/proc/sys/kernel/core_pattern", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
close(1)                                = 0
dup2(3, 1)                              = 1
close(3)                                = 0
write(1, "\n", 1)                       = 1
...
+++ exited with 0 +++
root@xxx:~# cat /proc/sys/kernel/core_pattern

root@xxx:~#

If you want to take a look at the actual implementation of open/read/write/close for sysfs files you can check /kernel/sysctl.c. There are different tables present for different sysctl facilities e.g. kernel, vm, etc.

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
  • So I conclude it's a documentation bug in `man core`: Empty means an empty line, not an empty file. Great work, btw. – Juergen Sep 09 '21 at 18:52