mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-24 13:06:14 +01:00
credentials: Invalid Linux struct ucred means "no information"
On Linux, if getsockopt SO_PEERCRED is used on a TCP socket, one might expect it to fail with an appropriate error like ENOTSUP or EPROTONOSUPPORT. However, it appears that in fact it succeeds, but yields a credentials structure with pid 0, uid -1 and gid -1. These are not real process, user and group IDs that can be allocated to a real process (pid 0 needs to be reserved to give kill(0) its documented special semantics, and similarly uid and gid -1 need to be reserved for setresuid() and setresgid()) so it is not meaningful to signal them to high-level API users. An API user with Linux-specific knowledge can still inspect these fields via g_credentials_get_native() if desired. Similarly, if SO_PASSCRED is used to receive a SCM_CREDENTIALS message on a receiving Unix socket, but the sending socket had not enabled SO_PASSCRED at the time that the message was sent, it is possible for it to succeed but yield a credentials structure with pid 0, uid /proc/sys/kernel/overflowuid and gid /proc/sys/kernel/overflowgid. Even if we were to read those pseudo-files, we cannot distinguish between the overflow IDs and a real process that legitimately has the same IDs (typically they are set to 'nobody' and 'nogroup', which can be used by a real process), so we detect this situation by noticing that pid == 0, and to save syscalls we do not read the overflow IDs from /proc at all. This results in a small API change: g_credentials_is_same_user() now returns FALSE if we compare two credentials structures that are both invalid. This seems like reasonable, conservative behaviour: if we cannot prove that they are the same user, we should assume they are not. Signed-off-by: Simon McVittie <smcv@collabora.com>
This commit is contained in:
parent
ef1035d9d8
commit
1485a97d80
@ -265,6 +265,35 @@ g_credentials_to_string (GCredentials *credentials)
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
||||
#if G_CREDENTIALS_USE_LINUX_UCRED
|
||||
/*
|
||||
* Check whether @native contains invalid data. If getsockopt SO_PEERCRED
|
||||
* is used on a TCP socket, it succeeds but yields a credentials structure
|
||||
* with pid 0, uid -1 and gid -1. Similarly, if SO_PASSCRED is used on a
|
||||
* receiving Unix socket when the sending socket did not also enable
|
||||
* SO_PASSCRED, it can succeed but yield a credentials structure with
|
||||
* pid 0, uid /proc/sys/kernel/overflowuid and gid
|
||||
* /proc/sys/kernel/overflowgid.
|
||||
*/
|
||||
static gboolean
|
||||
linux_ucred_check_valid (struct ucred *native,
|
||||
GError **error)
|
||||
{
|
||||
if (native->pid == 0
|
||||
|| native->uid == -1
|
||||
|| native->gid == -1)
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_INVALID_DATA,
|
||||
_("GCredentials contains invalid data"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* g_credentials_is_same_user:
|
||||
* @credentials: A #GCredentials.
|
||||
@ -294,7 +323,8 @@ g_credentials_is_same_user (GCredentials *credentials,
|
||||
|
||||
ret = FALSE;
|
||||
#if G_CREDENTIALS_USE_LINUX_UCRED
|
||||
if (credentials->native.uid == other_credentials->native.uid)
|
||||
if (linux_ucred_check_valid (&credentials->native, NULL)
|
||||
&& credentials->native.uid == other_credentials->native.uid)
|
||||
ret = TRUE;
|
||||
#elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
|
||||
if (credentials->native.cmcred_euid == other_credentials->native.cmcred_euid)
|
||||
@ -453,7 +483,10 @@ g_credentials_get_unix_user (GCredentials *credentials,
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, -1);
|
||||
|
||||
#if G_CREDENTIALS_USE_LINUX_UCRED
|
||||
ret = credentials->native.uid;
|
||||
if (linux_ucred_check_valid (&credentials->native, error))
|
||||
ret = credentials->native.uid;
|
||||
else
|
||||
ret = -1;
|
||||
#elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
|
||||
ret = credentials->native.cmcred_euid;
|
||||
#elif G_CREDENTIALS_USE_NETBSD_UNPCBID
|
||||
@ -499,7 +532,10 @@ g_credentials_get_unix_pid (GCredentials *credentials,
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, -1);
|
||||
|
||||
#if G_CREDENTIALS_USE_LINUX_UCRED
|
||||
ret = credentials->native.pid;
|
||||
if (linux_ucred_check_valid (&credentials->native, error))
|
||||
ret = credentials->native.pid;
|
||||
else
|
||||
ret = -1;
|
||||
#elif G_CREDENTIALS_USE_FREEBSD_CMSGCRED
|
||||
ret = credentials->native.cmcred_pid;
|
||||
#elif G_CREDENTIALS_USE_NETBSD_UNPCBID
|
||||
|
Loading…
Reference in New Issue
Block a user