Bug 276043 - [patch] md5(1) et al are broken when reading the last argument because of capsicum(4) code
Summary: [patch] md5(1) et al are broken when reading the last argument because of cap...
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: 14.0-STABLE
Hardware: Any Any
: --- Affects Only Me
Assignee: Mark Johnston
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-12-31 20:59 UTC by Ricardo Branco
Modified: 2024-01-16 14:53 UTC (History)
3 users (show)

See Also:
markj: mfc-stable14+
markj: mfc-stable13+


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ricardo Branco 2023-12-31 20:59:27 UTC
I was looking why the output of `md5 /compat/linux/proc/cpuinfo` is different from `cat /compat/linux/proc/cpuinfo | md5` and came across this code in sbin/md5/md5.c:

```
        char block[4096];
...
        while ((len = fread(block, 1, sizeof(block), f)) > 0) {
```

```

The issue is a truncated read as confirmed by truss and GNU wc:

```
$ sudo truss md5 /compat/linux/proc/cpuinfo 
...
read(3,"processor\t: 0\nvendor_id\t: Gen"...,4096) = 3549 (0xddd)
...
```

It obviously affects all tools using libc when comparing the output of wc vs. GNU wc:

```
$ wc -m /compat/linux/proc/cpuinfo
    3549 /compat/linux/proc/cpuinfo
$ gwc -m /compat/linux/proc/cpuinfo
3685 /compat/linux/proc/cpuinfo
```
Comment 1 Konstantin Belousov freebsd_committer freebsd_triage 2024-01-01 20:10:06 UTC
Could you please provide minimal C repro?  It is not clear to me in what way
read(2) from stdio (fread(3)) is different from read(2) issued by gnu wc.
Comment 2 Ricardo Branco 2024-01-02 21:46:28 UTC
I figured out the problematic code at:

```
                        /*
                         * XXX Enter capability mode on the last argv file.
                         * When a casper file service or other approach is
                         * available, switch to that and enter capability mode
                         * earlier.
                         */
                        if (*(argv + 1) == NULL) {
#ifdef HAVE_CAPSICUM
                                cap_rights_init(&rights, CAP_READ, CAP_FSTAT);
                                if (caph_rights_limit(fileno(f), &rights) < 0 ||
                                    caph_enter() < 0)
                                        err(1, "capsicum");
#endif
                        }
```

So md5 works if I pass /dev/null as the last argument:

$ md5 /compat/linux/proc/cpuinfo
MD5 (/compat/linux/proc/cpuinfo) = 36966b53dc9e57113b2b7637d8b51720
$ md5 /compat/linux/proc/cpuinfo /dev/null
MD5 (/compat/linux/proc/cpuinfo) = 142e18c701aa58b0e691920e2bf98e56
MD5 (/dev/null) = d41d8cd98f00b204e9800998ecf8427e
Comment 3 Ricardo Branco 2024-01-02 21:50:47 UTC
Adding `#undef HAVE_CAPSICUM` fixed it for me.
Comment 4 Ricardo Branco 2024-01-02 21:52:14 UTC
As for wc(1), it's another story as it calls stat(1) and just shows st_size if S_ISREG(). I will suggest a patch soon.
Comment 5 Ricardo Branco 2024-01-02 22:15:54 UTC
(In reply to Ricardo Branco from comment #4)

wc(1) also fails because of capsicum as this patch is not enough:

```
-               if (S_ISREG(sb.st_mode)) {
+               /* Don't do it on pseudo-filesystems that advertize a zero size */
+               if (S_ISREG(sb.st_mode) && sb.st_size > 0) {
```

It now returns the result of a truncated read:

```
$ /usr/obj/usr/src/amd64.amd64/usr.bin/wc/wc -m /compat/linux/proc/cpuinfo 
    3549 /compat/linux/proc/cpuinfo
```
Comment 6 Mark Johnston freebsd_committer freebsd_triage 2024-01-02 22:27:06 UTC
(In reply to Ricardo Branco from comment #5)
The problem is mostly specific to cpuinfo.  The handler calls kernel_sysctl() to read the HW_MODEL sysctl (I guess because cpu_model[] is static?), and that's not permitted in capability mode.

Probably the best solution is to simply permit reading HW_MODEL in capability mode.
Comment 7 Mark Johnston freebsd_committer freebsd_triage 2024-01-02 22:28:44 UTC
In particular, the file is legitimately different when read from within a capsicum sandbox:

> model name    : AMD Ryzen 9 7950X3D 16-Core Processor          
655c655
< model name    : unknown

so the difference in output is "expected".
Comment 8 Mark Johnston freebsd_committer freebsd_triage 2024-01-02 22:59:48 UTC
If you are able and willing to test a kernel patch, please give this a try: https://reviews.freebsd.org/D43281
Comment 9 Ricardo Branco 2024-01-03 12:52:20 UTC
(In reply to Mark Johnston from comment #8)
I tested the patch and it works.

Please don't close this bug until https://github.com/freebsd/freebsd-src/pull/984#issuecomment-1874667265 is addressed.

Cheers,
R
Comment 10 Mark Johnston freebsd_committer freebsd_triage 2024-01-03 14:31:06 UTC
(In reply to Ricardo Branco from comment #9)
Thanks!

Do you plan to work on the md5 issue?
Comment 11 Ricardo Branco 2024-01-03 14:38:26 UTC
(In reply to Mark Johnston from comment #10)
Yes.
Comment 12 Ricardo Branco 2024-01-03 18:01:40 UTC
Hopefully fixed by https://github.com/freebsd/freebsd-src/pull/988
Comment 13 commit-hook freebsd_committer freebsd_triage 2024-01-04 13:41:26 UTC
A commit in branch main references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=d74a742704eb81f0c6f4aa83e4cb0de26a81c400

commit d74a742704eb81f0c6f4aa83e4cb0de26a81c400
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2024-01-04 13:25:05 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2024-01-04 13:39:53 +0000

    linprocfs: Avoid using a sysctl to get the CPU model string

    This will fail if the reading process is in capability mode.  Just copy
    the string directly.

    PR:             276043
    Reviewed by:    emaste, imp, kib
    Reported and tested by: Ricardo Branco <rbranco@suse.com>
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D43281

 sys/compat/linprocfs/linprocfs.c | 11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)
Comment 14 commit-hook freebsd_committer freebsd_triage 2024-01-11 14:33:16 UTC
A commit in branch stable/14 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=b2dfbd772e887d722da0aad1ea9c1ce14e65f47d

commit b2dfbd772e887d722da0aad1ea9c1ce14e65f47d
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2024-01-04 13:25:05 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2024-01-11 14:19:07 +0000

    linprocfs: Avoid using a sysctl to get the CPU model string

    This will fail if the reading process is in capability mode.  Just copy
    the string directly.

    PR:             276043
    Reviewed by:    emaste, imp, kib
    Reported and tested by: Ricardo Branco <rbranco@suse.com>
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D43281

    (cherry picked from commit d74a742704eb81f0c6f4aa83e4cb0de26a81c400)

 sys/compat/linprocfs/linprocfs.c | 11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)
Comment 15 commit-hook freebsd_committer freebsd_triage 2024-01-11 14:36:18 UTC
A commit in branch stable/13 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=e3212b779ae2938428e087ac05c52e484cf2a6c2

commit e3212b779ae2938428e087ac05c52e484cf2a6c2
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2024-01-04 13:25:05 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2024-01-11 14:33:15 +0000

    linprocfs: Avoid using a sysctl to get the CPU model string

    This will fail if the reading process is in capability mode.  Just copy
    the string directly.

    PR:             276043
    Reviewed by:    emaste, imp, kib
    Reported and tested by: Ricardo Branco <rbranco@suse.com>
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D43281

    (cherry picked from commit d74a742704eb81f0c6f4aa83e4cb0de26a81c400)

 sys/compat/linprocfs/linprocfs.c | 11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)
Comment 16 Ricardo Branco 2024-01-11 14:41:56 UTC
Kind remind that the issue is not solved until a fix like https://github.com/freebsd/freebsd-src/pull/984#issuecomment-1874667265 is merged.

Do I create another bug or reopen this one?
Comment 17 Ricardo Branco 2024-01-11 14:43:24 UTC
Sorry I meant this fix: https://github.com/freebsd/freebsd-src/pull/988
Comment 18 Ricardo Branco 2024-01-16 14:53:30 UTC
My PR was merged.

I wish to thank everyone involved in the resolution of this bug.  The unlikely coincidence of a restricted path as the last argument made me research & fix like 3 or 4 other bugs related to some tools not being able to read files in procfs.