inotify, faccessat2, fsync for Linux programs, and D-Bus credentials

What installing and starting Epiphany ran into:

- inotify: inotify_init/init1, add_watch, rm_watch, as a new kind of event
  descriptor. The filesystem reports creates, deletes, renames (with a
  cookie pairing MOVED_FROM and MOVED_TO), writes, close-after-write,
  truncation and attribute changes, to watches on the inode and on its
  directory with the name. ONESHOT, MASK_ADD, MASK_CREATE, ONLYDIR,
  DONT_FOLLOW, IGNORED on removal, Q_OVERFLOW, and Linux's coalescing of
  repeated events. The hooks cost one load when nothing is watched. Without
  it GLib found no file monitor and GNOME programs aborted.
- FIONREAD on inotify descriptors and pipes (inotifywait sizes its buffer
  by it).
- fsync and fdatasync had no Linux numbers since the first commit: GLib's
  atomic writes, gtk-update-icon-cache and dbus-uuidgen all got ENOSYS.
- faccessat2, the flags-taking faccessat musl uses for any flags.
- sendmsg accepts SCM_CREDENTIALS when they are the sender's own, as Linux
  checks; GDBus sends them in every handshake and was refused with EINVAL.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
Nexoniarz 2026-10-25 06:40:28 +01:00
commit 3113eff7fe
9 changed files with 590 additions and 9 deletions

View file

@ -900,10 +900,31 @@ scm_gather(struct msghdr *m, struct file **fs, int *nfp)
}
fs[(*nfp)++] = filedup(f);
}
} else if (c->cmsg_level == SOL_SOCKET && c->cmsg_type == 2 /* SCM_CREDENTIALS */) {
// Credentials, which GDBus sends with the first byte of every
// D-Bus connection. Checked as Linux checks them -- they must be
// the sender's own, or the sender root -- and then not delivered:
// nothing here sets SO_PASSCRED to receive them, and the D-Bus
// daemon asks SO_PEERCRED instead, which answers the same question
// from the kernel's side. Refusing them made every GNOME program
// fail its D-Bus handshake ("Error sending credentials").
struct { int pid; uint uid, gid; } cr;
struct proc *me = myproc();
if (c->cmsg_len < CMSG_LEN(sizeof(cr))) {
r = -EINVAL;
goto fail;
}
memmove(&cr, CMSG_DATA(c), sizeof(cr));
if (me->euid != 0 &&
(cr.pid != me->tgid ||
(cr.uid != me->uid && cr.uid != me->euid) ||
(cr.gid != me->gid && cr.gid != me->egid))) {
r = -EPERM;
goto fail;
}
} else if (c->cmsg_level == SOL_SOCKET) {
// SCM_CREDENTIALS and friends. Refused rather than ignored: a
// caller that asked to pass credentials and was told yes would
// believe the receiver got them.
// Anything else. Refused rather than ignored: a caller that asked
// for something and was told yes would believe it happened.
r = -EINVAL;
goto fail;
}