With SD_VARLINK_SERVER_ROOT_ONLY, we refuse all unprivileged operations.
This is silly, the user can and should be able to do anything that doesn't
require privileges.
E.g.:
$ SYSTEMD_LOG_LEVEL=debug varlinkctl introspect /usr/lib/systemd/systemd-pcrextend
Forking off Varlink child process '/usr/lib/systemd/systemd-pcrextend'.
Successfully forked off '(sd-vlexec)' as PID 568993.
varlink: Setting state idle-client
json-stream: Sending message: {"method":"org.varlink.service.GetInterfaceDescription","parameters":{"interface":"io.systemd.PCRExtend"}}
Skipping PR_SET_MM, as we don't have privileges.
varlink: Changing state idle-client → calling
varlink: Unprivileged client attempted connection, refusing.
Failed to run Varlink event loop: Operation not permitted
json-stream: Got POLLHUP from socket.
varlink: Changing state calling → pending-disconnect
varlink: Connection was closed.
Failed to issue org.varlink.service.GetInterfaceDescription() varlink call: Connection reset by peer
This and similar commands now work, e.g.
$ SYSTEMD_LOG_LEVEL=debug varlinkctl call --more ./build/bootctl io.systemd.BootControl.ListBootEntries {}
...
Failed to open directory "/efi": No such file or directory
File system "/boot" is not a FAT EFI System Partition (ESP) file system.
...
Method call failed: Permission denied
{
"origin" : "linux",
"errno" : 13,
"errnoName" : "EACCES"
}
Which is fine — we lack privileges to actually return a useful answer, but the
call itself should go through.
I didn't touch udevd, which refuses to run if it is not root, and does a lot of
privileged setup, so would refuse to start even if the check was removed.
r = varlink_server_new(
&varlink_server,
- SD_VARLINK_SERVER_ROOT_ONLY|SD_VARLINK_SERVER_ALLOW_FD_PASSING_INPUT,
+ SD_VARLINK_SERVER_ROOT_ONLY |
+ SD_VARLINK_SERVER_MYSELF_ONLY |
+ SD_VARLINK_SERVER_ALLOW_FD_PASSING_INPUT,
/* userdata= */ NULL);
if (r < 0)
return log_error_errno(r, "Failed to allocate Varlink server: %m");
r = varlink_server_new(
&varlink_server,
- SD_VARLINK_SERVER_ROOT_ONLY|
- SD_VARLINK_SERVER_HANDLE_SIGINT|
+ SD_VARLINK_SERVER_ROOT_ONLY |
+ SD_VARLINK_SERVER_MYSELF_ONLY |
+ SD_VARLINK_SERVER_HANDLE_SIGINT |
SD_VARLINK_SERVER_HANDLE_SIGTERM,
/* userdata= */ NULL);
if (r < 0)
_cleanup_(sd_varlink_server_unrefp) sd_varlink_server *varlink_server = NULL;
int r;
- r = varlink_server_new(&varlink_server, SD_VARLINK_SERVER_ROOT_ONLY, /* userdata= */ NULL);
+ r = varlink_server_new(&varlink_server,
+ SD_VARLINK_SERVER_ROOT_ONLY | SD_VARLINK_SERVER_MYSELF_ONLY,
+ /* userdata= */ NULL);
if (r < 0)
return log_error_errno(r, "Failed to allocate Varlink server: %m");
/* Invocation as Varlink service */
- r = varlink_server_new(&varlink_server, SD_VARLINK_SERVER_ROOT_ONLY, NULL);
+ r = varlink_server_new(&varlink_server,
+ SD_VARLINK_SERVER_ROOT_ONLY | SD_VARLINK_SERVER_MYSELF_ONLY,
+ /* userdata= */ NULL);
if (r < 0)
return log_error_errno(r, "Failed to allocate Varlink server: %m");
/* Invocation as Varlink service */
- r = varlink_server_new(
- &varlink_server,
- SD_VARLINK_SERVER_ROOT_ONLY,
- /* userdata= */ NULL);
+ r = varlink_server_new(&varlink_server,
+ SD_VARLINK_SERVER_ROOT_ONLY | SD_VARLINK_SERVER_MYSELF_ONLY,
+ /* userdata= */ NULL);
if (r < 0)
return log_error_errno(r, "Failed to allocate Varlink server: %m");