# Non-root users can change hw.snd.default_unit sysctl



## eldaemon (May 22, 2020)

I'm a little perplexed to have accidentally found that non-root users (even ones denied access to /dev/mixer) can adjust hw.snd.default_unit. I assume non-root users can adjust some other sysctls.

I thought sysctl would have been restricted entirely to root.

I would appreciate any insight here and security-related adjustments I can make.

Thank you!


----------



## George (May 22, 2020)

sysctl(9) shows the possible permissions. E.g. CTLFLAG_ANYBODY means that any user or process can write to this sysctl.


----------



## eldaemon (May 22, 2020)

Is there any way that I can adjust that? Or would I have to modify the kernel source and recompile?


----------



## eldaemon (May 26, 2020)

Doing some more digging into this.


```
# grep -r CTLFLAG_ANYBODY /usr/src/sys
/usr/src/sys/security/mac_biba/mac_biba.c:     * Treat sysctl variables without CTLFLAG_ANYBODY flag as biba/high,
/usr/src/sys/security/mac_biba/mac_biba.c:    if (req->newptr != NULL && (oidp->oid_kind & CTLFLAG_ANYBODY) == 0) {
/usr/src/sys/security/mac_lomac/mac_lomac.c:     * Treat sysctl variables without CTLFLAG_ANYBODY flag as lomac/high,
/usr/src/sys/security/mac_lomac/mac_lomac.c:    if (req->newptr != NULL && (oidp->oid_kind & CTLFLAG_ANYBODY) == 0) {
/usr/src/sys/fs/devfs/devfs_devs.c:    CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_ANYBODY|CTLFLAG_MPSAFE,
/usr/src/sys/kern/kern_sysctl.c:    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE
/usr/src/sys/kern/kern_sysctl.c:    if (req->newptr && !(oid->oid_kind & CTLFLAG_ANYBODY)) {
/usr/src/sys/kern/imgact_binmisc.c:    CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_RW|CTLFLAG_ANYBODY, NULL, IBC_LOOKUP,
/usr/src/sys/kern/imgact_binmisc.c:    CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_RD|CTLFLAG_ANYBODY, NULL, IBC_LIST,
/usr/src/sys/kern/kern_proc.c:    CTLFLAG_RW | CTLFLAG_CAPWR | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE,
/usr/src/sys/kern/kern_proc.c:    CTLFLAG_ANYBODY | CTLFLAG_MPSAFE, sysctl_kern_proc_rlimit,
/usr/src/sys/kern/kern_proc.c:    CTLFLAG_ANYBODY | CTLFLAG_MPSAFE, sysctl_kern_proc_osrel,
/usr/src/sys/sys/sysctl.h:#define    CTLFLAG_ANYBODY    0x10000000    /* All users can set this var */
/usr/src/sys/dev/atkbdc/psm.c:        "softbuttons_y", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "softbutton2_x", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "softbutton3_x", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "directional_scrolls", CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "max_x", CTLFLAG_RD|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "max_y", CTLFLAG_RD|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "two_finger_scroll", CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "min_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "max_pressure", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "max_width", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "margin_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "margin_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "margin_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "margin_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "na_top", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "na_right", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "na_bottom", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "na_left", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "window_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "window_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "multiplicator", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "weight_current", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "weight_previous", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "weight_previous_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "weight_len_squared", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "div_max_na", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "div_len", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "tap_max_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "tap_min_queue", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "taphold_timeout", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "vscroll_hor_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "vscroll_ver_area", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "vscroll_min_delta", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "vscroll_div_min", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "vscroll_div_max", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "touchpad_off", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "three_finger_drag", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "natural_scroll", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "sensitivity", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "negative_inertia", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "upper_plateau", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "backup_range", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "drag_hysteresis", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "minimum_drag", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "up_threshold", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "threshold", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "jenks_curvature", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "z_time", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "press_to_select", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/atkbdc/psm.c:        "skip_backups", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
/usr/src/sys/dev/acpi_support/acpi_asus.c:                CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY,
/usr/src/sys/dev/acpi_support/acpi_panasonic.c:            CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY,
/usr/src/sys/dev/acpi_support/acpi_fujitsu.c:            CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY,
/usr/src/sys/dev/acpi_support/acpi_toshiba.c:            CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY,
/usr/src/sys/dev/sound/pcm/sound.c:        CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_ANYBODY,
/usr/src/sys/dev/asmc/asmc.c:            CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY,
```

Easiest place to adjust it would probably be /usr/src/sys/sys/sysctl.h, changing the #define.

I wonder if CTLFLAG_ANYBODY is a good idea at all. Might be a good mailing list discussion, what do you think?


----------



## ralphbsz (May 27, 2020)

AFAIK, the sysctl mechanism has relatively coarse-grain control about who can read and modify values: various flavors of root, or anyone. In particular, it has no notion that console-related sysctls (such as adjustment of keyboard, mouse, display and sound) should be restricted to the user currently logged into the console. In practice, that wouldn't even be possible, since multiple users can be logged into the console at the same time. And on some hardware, you can have multiple Xwindows sessions on multiple displays (the old HP-UX machines were famous for doing multi-user X on a single machine, with the display variable not being :0.0), at which point adjusting things like "audio" becomes very complex.

Fundamentally, this is a problem that has not been completely solved.

Linux isn't much better in this regard. I discovered a while ago that adjusting the backlight of the console display on Raspbian requires root privileges. That's sort of the opposite problem, when even the person who is running on the physical console (either in CLI mode or in X) can't adjust the screen brightness.

Before you go to the mailing list, try to come up with a simple and coherent proposal, which you might get some helpful input on here.


----------



## George (May 27, 2020)

One could remove permissions on /sbin/sysctl. But then programms could still call sysctlbyname(3)..

Edit: Can you describe a scenario in which changing snd.default_unit by a non-root user would be undesirable?

I think even on Windows you don't need root privileges to direct sound to e.g. headphones.


----------



## eldaemon (May 28, 2020)

Elazar said:


> One could remove permissions on /sbin/sysctl. But then programms could still call sysctlbyname(3)..
> 
> Edit: Can you describe a scenario in which changing snd.default_unit by a non-root user would be undesirable?
> 
> I think even on Windows you don't need root privileges to direct sound to e.g. headphones.



I'm sure there's some possible issues. Plugging in a microphone and making it the default audio interface. Or a usb interface with line out to record audio output. But any user account being able to change that device selection (even if they can't change mixer settings or read/write sound) is kind of ridiculous.


----------



## George (May 29, 2020)

In Windows you don't need to be root/administrator either.
53 How To: Change the Default Playback Device in Windows 10

Make a custom kernel?


----------



## eldaemon (May 29, 2020)

Elazar said:


> In Windows you don't need to be root/administrator either.
> 53 How To: Change the Default Playback Device in Windows 10
> 
> Make a custom kernel?



I didn't think that being like Windows was considered adequate security.

I'll probably make a simple patch for this and try it out later.


----------



## shkhln (May 29, 2020)

What's ridiculous is this very thread. Either present a real, no physical access, threat scenario or tone down your claims a bit.


----------



## eldaemon (May 29, 2020)

Should non-root users be able to eject CDs no matter what, unless the kernel is recompiled?

I just don't understand the logic of how it's a good thing. Random users messing with sysctl (granted, just a couple functions) is kind of crazy to me.


----------



## shkhln (May 29, 2020)

eldaemon said:


> Should non-root users be able to eject CDs no matter what, unless the kernel is recompiled?



Why not? They won't be able to use a CD drive otherwise. (It also has an eject button, by the way.)


----------



## memreflect (May 30, 2020)

shkhln said:


> Why not? They won't be able to use a CD drive otherwise. (It also has an eject button, by the way.)


And non-root users should also be able to plug in any USB device they want as well, right?  After all, only Windows is vulnerable to privilege escalation bugs, right?  

However, I agree that there's no security-focused reason to require superuser privileges to change the default sound output device.  What's a user going to do?  Play a song through the speakers instead of headphones?  Now if non-root users could change the pin configuration, that would be cause for a bit of concern.  Teleconferencing would be problematic if someone messed up the pin configuration and disabled audio input/output as a consequence without being able to restore the original behavior until the next reboot.


----------



## ralphbsz (May 30, 2020)

The traditional Unix security model (from which the one used by Windows is mostly derived) is built around the idea that the OS abstracts and virtualizes all physical resources, controls their usage, both by who can do what, and how much they can do. For example, in the old days (50s), any program could access the whole disk drive. I've still written "programs" (meaning JCL decks on an IBM mainframe) where I, as an individual user, could put data on specific cylinders of a specific disk drive, and the only thing that prevented me from overwriting someone else's data was a gentleman's agreement. Modern operating systems (such as Unix, or VMS, or DOS/360) fixed that with file systems (meaning the decision which part of the disk holds what data was left to the OS), and with access control (for example, in most cases I can read and write my own files, but probably not the ones of other users). Part of the resource control in the operating system is to also check that I haven't used too many resources. Today we call that quota; in the old days, I had to go to the computer center director and ask that they please give our department another 2 disk drives, in addition to the ~25 we already had, and those drives were the size of washing machines). Part of access control is to check that certain particularly valuable resources are only used by authorized people; we all remember computers on which only certain users were allowed to dial out via modems to transfer data across the country.

This model worked really well with resources that are frangible, such as disks (which can be cut into tiny pieces, called sectors, and those sectors handed out to individual users). And where things are interchangeable: I don't care whether I get sector X or Y, or whether my packets travel on modem A or modem B. The other thing that doesn't factor into the permission and quota checking is where the user is located: I can use my 10 MB of disk quote, whether I'm sitting in my office, or whether I'm logged in from the computer room itself, or whether I'm dialing in from home via 300 baud modem (BTDT).

Where this model fails is with physical resources that are wholly under the control of a single user, typically the console. Today, the CD-ROM drive is typically built into the computer. And most computers that are not headless servers have exactly one monitor, keyboard, and mouse. We can usually identify really well who is physically using that hardware. A good authentication mechanism might be: The CD-ROM can only be used by the person who is logged in on the console. Sound good? This could even be implemented with some difficulty. Except that there is a variety of problems with it. To begin with, more than one user can be logged into "the console" (for example, on my server in the basement, I usually have root logged into the first virtual console, just for checking things, and sometimes my non-root acound on the second one if I want to quickly do some work). Who should own the CD-ROM? What if my wife wants to quickly write a CD while I'm sitting at the keyboard debugging a temperature sensor? She could just give me the blank CD, tell me "please put that into the CD tray, I'll log in remotely from my laptop and get it done while sitting on the sofa)". But if the person logged into the physical console by default owns all the user-accessible devices, my wife would get mad at me, and we can't have that.

Now, with sound devices, I admit that sharing those with other users is not a typical use case. But Unix by default has no mechanism for changing ownership or protection on all console-attached devices upon logging in. Either the sound hardware (devices) are accessible to everyone, or only to root, or to a particular user who owns it, and everything else gets REALLY hard.

By the way, I understand the concern. If any random logged-in person could control the sound (or video!) hardware, then they could turn on the microphone, and listen to you as you are using the computer. The risk is obvious. I just don't know a reasonable way to fix that. On systems where the GUI is deeply integrated into the OS (like the Mac or Windows), we have a very clear idea of who is logged into the GUI, and we can change permissions. FreeBSD doesn't work that way.


----------



## shkhln (May 30, 2020)

ralphbsz said:


> By the way, I understand the concern. If any random logged-in person could control the sound (or video!) hardware, then they could turn on the microphone, and listen to you as you are using the computer.



Well, I don't. Sound device access is controlled by access rights to the individual /dev/dsp*, /dev/dspW* and /dev/audio* nodes. (OP is fully aware of that.) No sure if it's possible to specifically disable the microphone, though.


----------



## ralphbsz (May 30, 2020)

Shkhln: Yes, that's the way it is implemented now. And given the way Unix and FreeBSD works, ownership and access rights are pretty much the only tools are our disposal, whether fine-grained or appropriate, or not. But in an ideal world, free of the strings of real-world implementations, it would be nice if the person who gets listened to (or who gets video recorded) could control whether they want to allow that. Or the person who has the headphones on could be the only one who can control the volume (and the selection of music, and many other aspects). The question is: How can we get reasonably close to that idea, with reasonably little work?


----------



## shkhln (May 30, 2020)

Remember, we are discussing a silly sysctl, not the entire Unix permission model. (In which case my #1 complaint would be one user group per file limitation.)



ralphbsz said:


> it would be nice if the person who gets listened to (or who gets video recorded) could control whether they want to allow that. Or the person who has the headphones on could be the only one who can control the volume (and the selection of music, and many other aspects).



Browsers ask permission, PulseAudio probably has something like that as well. Combine that with process sandboxing* and you are mostly already there. The operating system permissions will never be sufficiently precise, it doesn't have the understanding of different use cases with different (potentially contradictory) requirements.

* yes, I know FreeBSD is severely lagging on that front


----------



## ralphbsz (May 30, 2020)

Yeah, what would really help here would be if (a) sysctl's had an ownership/access control model like files in the file system, and (b) one could write ACLs in terms of roles: Not "if user id = ...", but "if this user is logged in on the console", or "if this user is currently acting as the sys admin", or "the user who is running the music player".

Any moment now, some old-timer (not me this time!) will come by and point out that Multics already had all this.


----------



## eldaemon (Jun 18, 2020)

I've made a few attempts writing patches. Changing the `#define CTLFLAG_ANYBODY` is futile, you can even allow all `sysctl` writes if you aren't careful.

There's one main if statement in kern_sysctl.c that seems to be involved. I don't quite understand what's going on as the only way I've found to secure sysctl involves blocking out reads of sysctl variables by non-root users, such as `hw.ncpu`.

I figure I'll keep messing with it to see if I have any luck.


----------



## eldaemon (Jun 21, 2020)

Alfonso Sicilia on the freebsd-hackers mailing list was incredibly helpful and wrote a patch that works perfectly.



			An option to ignore sysctl CTLFLAG_ANYBODY
		


Attached is a diff with his patch for 12.1. I'm sure it would work on others, though.


----------

