martinpitt / umockdev

Mock hardware devices for creating unit tests and bug reporting
https://launchpad.net/umockdev
GNU Lesser General Public License v2.1
312 stars 57 forks source link

Tune owner for umockdev dir/files #221

Open ikerexxe opened 11 months ago

ikerexxe commented 11 months ago

We'd like to be able to use umockdev as unprivileged users, but currently the directory and files that need to be accessed by umockdev are hardcoded as root.

Provide a way to tune the owner of the umockdev directory and files to another (unprivileged) user.

martinpitt commented 10 months ago

Can you please tell me the privilege/component structure of how you use umockdev? Are you using the CLI (umockdev-run) or the API to build the mock env? I suppose you build that from a root process and expect to use it from a non-root process?

For the CLI you could just run it via runuser, from the API you could just temporarily switch to the target user with seteuid(). But I suppose that's not possible somehow. Hence, I don't yet understand what kind of new API/CLI/feature you need to support your use case? I. e. where exactly would you like to specify the target user? An umockdev-run CLI option? An API call? Something else?

This information does not really belong into the recorded .umockdev file, as it's highly specific to the caller, not to the recorded device.

martinpitt commented 10 months ago

Also, what do you mean by "accessed"? Many devices are read-only for unpriv users by default, some are world writable. Does your non-root consumer need to write to them?

One option would be to record the permissions and owner into the .umockdev file, and restore the permissions (and the owner if running as root) in umockdev-run. But I don't really want to create world-writable files, they are kind of dangerous. So I'm interested in your specific use case.

ikerexxe commented 10 months ago

We use the CLI (umockdev-record and umockdev-run) to build the mock environment. Where can I find some documentation that explains how to user runuser? Perhaps we could use it.

I have one question regarding the operation of this tool. When we run umockdev-run does it write to the device? Or does it only read? I mean, as I understand it when you communicate with a physical device you need to read and write, but I don't know if this is the case here.

@madhuriupadhye can you confirm that you are doing the umockdev recording as root user?

martinpitt commented 10 months ago

@ikerexxe runuser is a standard util-linux thing, similar to su -c 'command' user, just nicer to use as it avoids a level of quoting.

BTW, for this problem the user that umockdev-record runs as isn't super important, only that it needs to be able to access the real devices for ioctl etc. recording. Your troubles (between root and sssd) happen on the replay side.

ikerexxe commented 10 months ago

@ikerexxe runuser is a standard util-linux thing, similar to su -c 'command' user, just nicer to use as it avoids a level of quoting.

We are using su, so I don't think runuser would help us.

martinpitt commented 10 months ago

No no, this isn't about su vs. runuser. I'm interested in a structural overview which components are in your test setup, i.e. how umockdev{-record,run} or the umockdev API hangs together with the things you want to test, and which privileges each process has, etc.

madhuriupadhye commented 10 months ago

We use the CLI (umockdev-record and umockdev-run) to build the mock environment. Where can I find some documentation that explains how to user runuser? Perhaps we could use it.

I have one question regarding the operation of this tool. When we run umockdev-run does it write to the device? Or does it only read? I mean, as I understand it when you communicate with a physical device you need to read and write, but I don't know if this is the case here.

@madhuriupadhye can you confirm that you are doing the umockdev recording as root user?

Yes, we did and doing recording as a root user.

martinpitt commented 10 months ago

@madhuriupadhye As I said, the recording side is much less interesting. I still need to understand how your root/non-root test processes and umockdev-run (or whatever else) hang together, and where the privilege boundaries are. There are several ways how permissions could be addressed/changed, but I need to understand your setup.

ikerexxe commented 10 months ago

I can only speak from the development side, and how the functionality works. I'll let Madhuri provide you the exact details about the testing environment.

All the communication from SSSD happens in a binary called passkey_child. Depending on the distribution it's owned by root or sssd and it has the following permissions 755. As said before, this is the binary that communicated with the FIDO2 device and it relies on libfido2 for that.

Note: if you are using Fedora 39+ you can install this binary by installing the sssd-passkeypackage. The file is present at /usr/libexec/sssd/passkey_child.

Do you miss any details?

alexey-tikhonov commented 10 months ago

passkey_child doesn't (shouldn't) have SUID bit (or any other file caps) set . It's executed by other SSSD processes that are run under configured user (either 'root' or 'sssd').

martinpitt commented 10 months ago

I'm still missing pretty much all of the details in this and this comment. I can guess that you run umockdev-run as root with some recording in the test setup, and then do something(?) that calls a process owned by a non-root user (which is now clarified to be passkey_child, running as sysuser sssd, right?), which is supposed to access the testbed. There's no suid involved anywhere, so I suppose it's simply called by the sssd.service daemon?

So the most obvious thing to do would be to run umockdev-run as user sssd, so that both that and root processes can access the testbed. But I guess you already tried that? What went wrong there? Perhaps that's much easier to fix than reimplementing Linux' ACL system in umockdev..

alexey-tikhonov commented 10 months ago

So the most obvious thing to do would be to run umockdev-run as user sssd

Would it work other way round: run umockdev-run as user sssd but passkey_child as user root? We strive to test both modes (privileged & unprivileged SSSD)

martinpitt commented 10 months ago

Sure, a root process has no trouble accessing files owned by any user. (Unless it drops CAP_DAC_OVERRIDE)

martinpitt commented 9 months ago

@ikerexxe @alexey-tikhonov Just to avoid misunderstandings: This isn't actionable for me right now, I'm still waiting for your input/details.

alexey-tikhonov commented 9 months ago

Meanwhile we realized that real tokens are (also) not accessible by non privileged users.

For this reason following udev rule was added to sssd-passkey package: https://github.com/SSSD/sssd/blob/master/contrib/90-sssd-token-access.rules.in

But looks like it doesn't work for mocked devices...

alexey-tikhonov commented 9 months ago

Sure, a root process has no trouble accessing files owned by any user. (Unless it drops CAP_DAC_OVERRIDE)

It does drop all capabilities.

This is how 'umockdev-run' is executed: https://github.com/SSSD/sssd-test-framework/blob/ff10c0fd5ed949ad426a2c9b5c3d47ac611643f8/sssd_test_framework/utils/authentication.py#L352

'run_su' script has 'chmod -R a+rwx $UMOCKDEV_DIR': https://github.com/SSSD/sssd-test-framework/blob/ff10c0fd5ed949ad426a2c9b5c3d47ac611643f8/sssd_test_framework/utils/authentication.py#L341C17-L341C45

But this doesn't help for some reason...

alexey-tikhonov commented 9 months ago

'run_su' script has 'chmod -R a+rwx $UMOCKDEV_DIR': https://github.com/SSSD/sssd-test-framework/blob/ff10c0fd5ed949ad426a2c9b5c3d47ac611643f8/sssd_test_framework/utils/authentication.py#L341C17-L341C45

But this doesn't help for some reason...

Ah, of course, it doesn't help because this is a source dir, that is being replayed, not a device file.

I wonder if it would work to just chown o+rw /dev/hidraw* in the test env...

alexey-tikhonov commented 9 months ago

So the most obvious thing to do would be to run umockdev-run as user sssd

@martinpitt, how will umockdev-run create a file under /dev/ then?

alexey-tikhonov commented 9 months ago

@martinpitt, is it possible to make following udev rule work with 'umockdev-run':

# cat ./usr/lib/udev/rules.d/90-sssd-token-access.rules
# this udev file should be used with udev 188 and newer
ACTION!="add|change", GOTO="sssd_end"

# Allow SSSD to access security tokens
SUBSYSTEM=="hidraw", ENV{ID_SECURITY_TOKEN}=="1", RUN{program}+="/usr/bin/setfacl -m u:sssd:rw $env{DEVNAME}"

LABEL="sssd_end"

?

alexey-tikhonov commented 8 months ago

I tried both 'runuser' and 'setpriv' without luck so far.

martinpitt commented 8 months ago

@alexey-tikhonov sorry for the late answer, this slipped through the cracks :cry:

umockdev doesn't run udev rules at all, so I'm afraid no. You'll have to call setfacl manually in your test after creating the mock env.

alexey-tikhonov commented 7 months ago

@martinpitt,

Usage:
  umockdev-run [OPTION?]  -- program [args..]

-- by the moment 'umockdev-run' starts execution of 'program', is mocked device file already available?

In our case 'program' is a script. I added setfacl -m u:sssd:rw /dev/hidraw* to this script and it fails with

setfacl: /dev/hidraw1: No such file or directory