Plain text interfaces lead to complicated, potentially insecure code (especially in C!), they're prone to race conditions and slow.
I wish it was possible to retrieve that information using real syscalls. I think it's a better approach than, for example, inventing a faster way to read procfs: https://lwn.net/Articles/813827/
Currently, but if this idea started when Linux was become popular the real data format would have been XML. It might have been nice at the time, but today we would have laughed at it and said how outdated and silly it looks probably.
% strace uptime 2> /tmp/strace && grep proc /tmp/strace
17:35:24 up 3 days, 7:47, 1 user, load average: 2.29, 1.85, 1.56
openat(AT_FDCWD, "/usr/lib/libprocps.so.8", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/proc/self/auxv", O_RDONLY) = 3
openat(AT_FDCWD, "/proc/sys/kernel/osrelease", O_RDONLY) = 3
openat(AT_FDCWD, "/proc/self/auxv", O_RDONLY) = 3
openat(AT_FDCWD, "/proc/uptime", O_RDONLY) = 3
openat(AT_FDCWD, "/proc/loadavg", O_RDONLY) = 4
You can still have easy abstractions while providing a way around them for times they don't work well (acquiring structured data)
it sounds fishy, but just because sysctl is a mess doesn't necessarily imply that structured kernel interfaces are a bad idea
eBPF recently added the ability to look through internal data structures through iterators [0] so instead of parsing text we can run a program that traverses through all the task_structs and pushes the exact information we want to userspace in the form the developer wants.
So, alongside other tradeoffs, it's more flexible than syscalls.
[0] https://developers.facebook.com/blog/post/2022/03/31/bpf-ite...
In return, the kernel side API for sysfs is also a lot cleaner and allows to more-or-less expose individual variables as tuning knobs for a driver.
Of course there are edge cases, and there are e.g. some binary interfaces as well (e.g. for providing direct register access, or implementing a firmware upload interface for a device).
ABI compat issues aside, I think that implementing "a standardized [structured] record format" as suggested in the comments here is a rather bad idea, going into exactly the wrong direction by adding complexity rather than reducing it, which would definitely cause even more parsing related issues in the long run.
I'd rather have structured file than to have open 30k files (for say conntrack)
Hell, just example from the article, /proc/<PID>/stat has 52 parameters. That would be 52 opens and reads with single value per file.
> ABI compat issues aside, I think that implementing "a standardized [structured] record format" as suggested in the comments here is a rather bad idea, going into exactly the wrong direction by adding complexity rather than reducing it, which would definitely cause even more parsing related issues in the long run.
It's literally the opposite. You have to implement it once on kernel side and once in userspace vs every special format that currently needs
You can't really prevent that. People do funny nonsense in other self-describing data formats like JSON and XML all the time too. There's only so much you can do with a framework.
But /proc is... extremely old, and very heavily used by userspace. In practice it's never going to change.
Sure but you will get more of that if the convention is too simplistic. "one file per value" breaks really fast, just cat /proc/net/nf_conntrack or even just proc/<pid>/stats and see just how many values single entry (file/connection) has.
Doesn't need to be some ASN.1 monstrosity, could be simple conventions like "this is how key/value proc/sys file should look, this is how tabular file should look etc."
Make all escaping use same syntax, make every table separator be \t etc.
> But /proc is... extremely old, and very heavily used by userspace. In practice it's never going to change.
eh, just mount it in /proc2
All sensible ones allow you to just pass an array of parameters to command execution and not worry about spaces in them
The way most sudoers files are set up, if you're in the wheel or sudo group, you're only a "sudo -i" from a root command prompt, so I'm not sure I see why this is a vulnerability. Can anyone elaborate?
/proc/<pid>/maps is similarly frustrating: there's no clear distinction between "special" maps (like the stack) and a file that might just happen to be named `[stack]`. Similarly, the handling for a mapped region on a deleted file is simply to append " (deleted)"[1].
[1]: https://github.com/woodruffw/procmaps.rs/blob/79bd474104e9b3...
Time to let go of the everything is a stream of unorganized characters
$ cat /proc/2001/stat | jc --proc
{"pid":2001,"comm":"my program with\nsp","state":"S","ppid":1888,"pgrp":2001,"session":1888,"tty_nr":34816,"tpg_id":2001,"flags":4202496,"minflt":428,"cminflt":0,"majflt":0,"cmajflt":0,"utime":0,"stime":0,"cutime":0,"cstime":0,"priority":20,"nice":0,"num_threads":1,"itrealvalue":0,"starttime":75513,"vsize":115900416,"rss":297,"rsslim":18446744073709551615,"startcode":4194304,"endcode":5100612,"startstack":140737020052256,"kstkeep":140737020050904,"kstkeip":140096699233308,"signal":0,"blocked":65536,"sigignore":4,"sigcatch":65538,"wchan":18446744072034584486,"nswap":0,"cnswap":0,"exit_signal":17,"processor":0,"rt_priority":0,"policy":0,"delayacct_blkio_ticks":0,"guest_time":0,"cguest_time":0,"start_data":7200240,"end_data":7236240,"start_brk":35389440,"arg_start":140737020057179,"arg_end":140737020057223,"env_start":140737020057223,"env_end":140737020059606,"exit_code":0,"state_pretty":"Sleeping in an interruptible wait"}
[0] https://kellyjonbrazil.github.io/jc/docs/parsers/proc_pid_st...Here's that commit, it has a comment with an overview of the kernel limits and caveats involved: https://github.com/git/git/commit/2d3491b117c6dd08e431acc390...
As pointed out in https://news.ycombinator.com/item?id=34098360, and contrary to the proc(5) man page, this assumption is incorrect for kernel threads.
But you're right that a more general parser would need to ignore what proc(5) has to say about the limit, and parse up to a limit of 64.
As far as I can tell the difference is because when you call prctl(2) with "PR_SET_NAME" it will get truncated to the "TASK_COMM_LEN" that proc(5) discusses. See this code in kernel/sys.c: https://github.com/torvalds/linux/blob/493ffd6605b2d3d4dc700...
This is the linux.git commit that changed it, before that kernel worker threads had to obey the same limit, it was first released with linux v4.18: https://github.com/torvalds/linux/commit/6b59808bfe482642287...
https://github.com/pixie-io/pixie/blob/bd82bb48ef4da7d6b05f2...
https://gitlab.com/psmisc/psmisc/-/blob/master/src/pstree.c#...
Besides, it wouldn't work, because you don't know in advance how many fields are there.
Like the post says: read the whole thing into memory and do a reverse search for the last ')', i.e. strrchr
Once you are aware of the problem, it's obvious how to solve it, but I do agree that the hidden danger here is not immediately obvious at first.