首页 > 代码库 > Mac OS X Kernel Basic User Credentials

Mac OS X Kernel Basic User Credentials

User Credentials

In order to understand security in OS X, it is important to understand that there are two security models at work. One of these is the kernel security model, which is based on users, groups, and very basic per-user and per-group rights, which are, in turn, coupled with access control lists for increased flexibility. The other is a user-level security model, which is based on keys, keychains, groups, users, password-based authentication, and a host of other details that are beyond the scope of this document.

The user-level security model (including the Keychain Manager and the Security Server) is beyond the scope of this document. The kernel security model, however, is of greater interest to kernel developers, and is much more straightforward than the user-level model. The kernel security model is based on two mechanisms: basic user credentials and ACL permissions. The first, basic user credentials, are passed around within the kernel to identify the current user and group of the calling process. The second authentication mechanism, access control lists (ACLs), provides access control at a finer level of granularity. One of the most important things to remember when working with credentials is that they are per process, not per context. This is important because a process may not be running as the console user. Two examples of this are processes started from an ssh session (since ssh runs in the startup context) and setuid programs (which run as a different user in the same login context).

It is crucial to be aware of these issues. If you are communicating with a setuid root GUI application in a user‘s login context, and if you are executing another application or are reading sensitive data, you probably want to treat it as if it had the same authority as the console user, not the authority of the effective user ID caused by running setuid. This is particularly problematic when dealing with programs that run as setuid root if the console user is not in the admin group. Failure to perform reasonable checks can lead to major security holes down the road.

However, this is not a hard and fast rule. Sometimes it is not obvious whether to use the credentials of the running process or those of the console user. In such cases, it is often reasonable to have a helper application show a dialog box on the console to require interaction from the console user. If this is not possible, a good rule of thumb is to assume the lesser of the privileges of the current and console users, as it is almost always better to have kernel code occasionally fail to provide a needed service than to provide that service unintentionally to an unauthorized user or process.

It is generally easier to determine the console user from a user space application than from kernel space code. Thus, you should generally do such checks from user space. If that is not possible, however, the variable console_user (maintained by the VFS subsystem) will give you the uid of the last owner of /dev/console (maintained by a bit of code in the chown system call). This is certainly not an ideal solution, but it does provide the most likely identity of the console user. Since this is only a "best guess," however, you should use this only if you cannot do appropriate checking in user space.

Basic User Credentials

Basic user credentials used in the kernel are stored in a variable of type struct ucred. These are mostly used in specialized parts of the kernel—generally in places where the determining factor in permissions is whether or not the caller is running as the root user.

This structure has four fields:

  • cr_ref—reference count (used internally)
  • cr_uid—user ID
  • cr_ngroups—number of groups in cr_groups
  • cr_groups[NGROUPS]—list of groups to which the user belongs

This structure has an internal reference counter to prevent unintentionally freeing the memory associated with it while it is still in use. For this reason, you should not indiscriminately copy this object but should instead either use crdup to duplicate it or use crcopy to duplicate it and (potentially) free the original. You should be sure to crfree any copies you might make. You can also create a new, empty ucred structure with crget.

The prototypes for these functions follow:

  • struct ucred *crdup(struct ucred *cr)
  • struct ucred *crcopy(struct ucred *cr)
  • struct ucred *crget(void)
  • void crfree(struct ucred *cr)

Note: Functions for working with basic user credential are not exported outside of the kernel, and thus are not generally available to kernel extensions.

Access Control Lists

Access control lists are a new feature in OS X v10.4. Access control lists are primarily used in the file system portion of the OS X kernel, and are supported through the use of the kauth API.

The kauth API is described in the header file /System/Library/Frameworks/Kernel.framework/Headers/sys/kauth.h. Because this API is still evolving, detailed documentation is not yet available.

SRC=https://developer.apple.com/library/prerelease/mac/documentation/Darwin/Conceptual/KernelProgramming/KernelProgramming.pdf

Mac OS X Kernel Basic User Credentials