|
Message-Id: <CDUBF46MT495.39NHTGIJ3S3V7@mussels> Date: Fri, 27 Aug 2021 10:05:21 -0300 From: Érico Nogueira <ericonr@...root.org> To: <musl@...ts.openwall.com> Subject: Re: What if the line in /proc/mounts is too long when calling getmntent_r? Unfortunately your message was sent all garbled (please try to stick to plain text email ;), so I'm reproducing it cleanly underneath with my answer: >Hi! > I want to get cgroups mount information from /proc/mounts, but when i calling struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int buflen), i got nothing... > I run the program in a container. > > alpine docker image: amd64/alpine:3.14 > musl: 1.2.2 > program: > > #include <stdio.h> > > #include <stdlib.h> > > #include <mntent.h> > > > #define CGROUP_MAX_VAL 512 > > > int main(void) > > { > > struct mntent ent; > > FILE *f; > > char buf[CGROUP_MAX_VAL]; > > > f = setmntent("/proc/mounts", "r"); > > if (f == NULL) { > > perror("setmntent"); > > exit(1); > > } > > > while (getmntent_r(f, &ent, buf, sizeof(buf)) != NULL) { > > printf("%s %s\n", ent.mnt_type, ent.mnt_opts); > > } The man page specifies that getmntent_r can return NULL on error, you should check errno to see if anything happened. In this case, it would be ERANGE, which tells you your buffer was too small. > > > endmntent(f); > > } > > contents of file "/proc/mounts" > > overlay / overlay rw,relatime,lowerdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/955/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/954/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/953/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/952/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/941/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/940/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/879/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/325/fs,upperdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/956/fs,workdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/956/work 0 0 > > proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0 > > tmpfs /dev tmpfs rw,nosuid,size=65536k,mode=755 0 0 > > devpts /dev/pts devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666 0 0 > > mqueue /dev/mqueue mqueue rw,nosuid,nodev,noexec,relatime 0 0 > > sysfs /sys sysfs ro,nosuid,nodev,noexec,relatime 0 0 > > tmpfs /sys/fs/cgroup tmpfs rw,nosuid,nodev,noexec,relatime,mode=755 0 0 > > cgroup /sys/fs/cgroup/systemd cgroup rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd 0 0 > > cgroup /sys/fs/cgroup/net_cls,net_prio cgroup rw,nosuid,nodev,noexec,relatime,net_prio,net_cls 0 0 > > cgroup /sys/fs/cgroup/pids cgroup rw,nosuid,nodev,noexec,relatime,pids 0 0 > > cgroup /sys/fs/cgroup/hugetlb cgroup rw,nosuid,nodev,noexec,relatime,hugetlb 0 0 > > cgroup /sys/fs/cgroup/cpuset cgroup rw,nosuid,nodev,noexec,relatime,cpuset 0 0 > > cgroup /sys/fs/cgroup/blkio cgroup rw,nosuid,nodev,noexec,relatime,blkio 0 0 > > cgroup /sys/fs/cgroup/devices cgroup rw,nosuid,nodev,noexec,relatime,devices 0 0 > > cgroup /sys/fs/cgroup/freezer cgroup rw,nosuid,nodev,noexec,relatime,freezer 0 0 > > cgroup /sys/fs/cgroup/cpu,cpuacct cgroup rw,nosuid,nodev,noexec,relatime,cpuacct,cpu 0 0 > > cgroup /sys/fs/cgroup/memory cgroup rw,nosuid,nodev,noexec,relatime,memory 0 0 > > cgroup /sys/fs/cgroup/perf_event cgroup rw,nosuid,nodev,noexec,relatime,perf_event 0 0 > > ... > > > I find the first line of the file /proc/mounts has 822 characters(In theory the 'overlay' could be even longer), more than CGROUP_MAX_VAL(512) defined in the proagram. Function fget in getmntent_r cann't get the whole line into linebuf, neither the character '\n'. And the function strchr(linebuf, '\n') returns false, causing program returnd. > The function struct mntent *getmntent(FILE *f) is a good chioce to deal this. But it can not be used in multiple threads, right? Correct, getmntent isn't thread safe. > Maybe the implementation of GNU libc struct mntent *__getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz) can be referenced. >From what I can see, glibc silently throws away any and all chars that don't fit in the provided buffer until it finds a newline. getmntent_r isn't actually specified, so I guess its behavior is a bit up to the implementation. Anyhow, musl's reports ERANGE properly (maybe the man page can be fixed to mention it?) and you should use a dynamic buffer in your program if you expect to deal with huge entries, and resize it if getmntent_r fails with ERANGE. > > thanks!
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.