util: unify SO_PEERCRED/SO_PEERSEC invocations
Introduce new call getpeercred() which internally just uses SO_PEERCRED but checks if the returned data is actually useful due to namespace quirks.
This commit is contained in:
@@ -579,6 +579,7 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_
|
||||
int getpeername_pretty(int fd, char **ret) {
|
||||
union sockaddr_union sa;
|
||||
socklen_t salen;
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(ret);
|
||||
@@ -593,9 +594,9 @@ int getpeername_pretty(int fd, char **ret) {
|
||||
/* UNIX connection sockets are anonymous, so let's use
|
||||
* PID/UID as pretty credentials instead */
|
||||
|
||||
salen = sizeof(ucred);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &salen) < 0)
|
||||
return -errno;
|
||||
r = getpeercred(fd, &ucred);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (asprintf(ret, "PID %lu/UID %lu", (unsigned long) ucred.pid, (unsigned long) ucred.pid) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -6117,3 +6117,61 @@ bool pid_valid(pid_t pid) {
|
||||
|
||||
return errno != ESRCH;
|
||||
}
|
||||
|
||||
int getpeercred(int fd, struct ucred *ucred) {
|
||||
socklen_t n = sizeof(struct ucred);
|
||||
struct ucred u;
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(ucred);
|
||||
|
||||
r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
if (n != sizeof(struct ucred))
|
||||
return -EIO;
|
||||
|
||||
/* Check if the data is actually useful and not suppressed due
|
||||
* to namespacing issues */
|
||||
if (u.pid <= 0)
|
||||
return -ENODATA;
|
||||
|
||||
*ucred = u;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getpeersec(int fd, char **ret) {
|
||||
socklen_t n = 64;
|
||||
char *s;
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(ret);
|
||||
|
||||
s = new0(char, n);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
|
||||
if (r < 0) {
|
||||
free(s);
|
||||
|
||||
if (errno != ERANGE)
|
||||
return -errno;
|
||||
|
||||
s = new0(char, n);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
|
||||
if (r < 0) {
|
||||
free(s);
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
*ret = s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <unistd.h>
|
||||
#include <locale.h>
|
||||
#include <mntent.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "macro.h"
|
||||
#include "time-util.h"
|
||||
@@ -811,3 +812,6 @@ int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *root_fd);
|
||||
int namespace_enter(int pidns_fd, int mntns_fd, int root_fd);
|
||||
|
||||
bool pid_valid(pid_t pid);
|
||||
|
||||
int getpeercred(int fd, struct ucred *ucred);
|
||||
int getpeersec(int fd, char **ret);
|
||||
|
||||
Reference in New Issue
Block a user