chiark
/
gitweb
/
~ianmdlvl
/
elogind.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Prep v232.2: Mask more unneeded functions
[elogind.git]
/
src
/
shared
/
clean-ipc.c
diff --git
a/src/shared/clean-ipc.c
b/src/shared/clean-ipc.c
index 95d6c421998ebfd1d2a593d773a88cc8f4523693..8c60bdc1f2be77ae301b7d95a96ccde5ac87690d 100644
(file)
--- a/
src/shared/clean-ipc.c
+++ b/
src/shared/clean-ipc.c
@@
-1,5
+1,3
@@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
/***
This file is part of systemd.
@@
-19,21
+17,44
@@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <mqueue.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
#include <sys/ipc.h>
#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <sys/sem.h>
#include <sys/msg.h>
#include <sys/msg.h>
+#include <sys/sem.h>
+#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/stat.h>
-#include <fcntl.h>
-#include <dirent.h>
-//#include <mqueue.h>
+#include <unistd.h>
-#include "util.h"
+#include "clean-ipc.h"
+#include "dirent-util.h"
+#include "fd-util.h"
+#include "fileio.h"
#include "formats-util.h"
#include "formats-util.h"
+#include "log.h"
+#include "macro.h"
+#include "string-util.h"
#include "strv.h"
#include "strv.h"
-#include "clean-ipc.h"
+#include "user-util.h"
+
+static bool match_uid_gid(uid_t subject_uid, gid_t subject_gid, uid_t delete_uid, gid_t delete_gid) {
-static int clean_sysvipc_shm(uid_t delete_uid) {
+ if (uid_is_valid(delete_uid) && subject_uid == delete_uid)
+ return true;
+
+ if (gid_is_valid(delete_gid) && subject_gid == delete_gid)
+ return true;
+
+ return false;
+}
+
+static int clean_sysvipc_shm(uid_t delete_uid, gid_t delete_gid) {
_cleanup_fclose_ FILE *f = NULL;
char line[LINE_MAX];
bool first = true;
_cleanup_fclose_ FILE *f = NULL;
char line[LINE_MAX];
bool first = true;
@@
-44,8
+65,7
@@
static int clean_sysvipc_shm(uid_t delete_uid) {
if (errno == ENOENT)
return 0;
if (errno == ENOENT)
return 0;
- log_warning_errno(errno, "Failed to open /proc/sysvipc/shm: %m");
- return -errno;
+ return log_warning_errno(errno, "Failed to open /proc/sysvipc/shm: %m");
}
FOREACH_LINE(line, f, goto fail) {
}
FOREACH_LINE(line, f, goto fail) {
@@
-69,7
+89,7
@@
static int clean_sysvipc_shm(uid_t delete_uid) {
if (n_attached > 0)
continue;
if (n_attached > 0)
continue;
- if (
uid != delete_uid
)
+ if (
!match_uid_gid(uid, gid, delete_uid, delete_gid)
)
continue;
if (shmctl(shmid, IPC_RMID, NULL) < 0) {
continue;
if (shmctl(shmid, IPC_RMID, NULL) < 0) {
@@
-78,19
+98,20
@@
static int clean_sysvipc_shm(uid_t delete_uid) {
if (errno == EIDRM || errno == EINVAL)
continue;
if (errno == EIDRM || errno == EINVAL)
continue;
- log_warning_errno(errno, "Failed to remove SysV shared memory segment %i: %m", shmid);
- ret = -errno;
- }
+ ret = log_warning_errno(errno,
+ "Failed to remove SysV shared memory segment %i: %m",
+ shmid);
+ } else
+ log_debug("Removed SysV shared memory segment %i.", shmid);
}
return ret;
fail:
}
return ret;
fail:
- log_warning_errno(errno, "Failed to read /proc/sysvipc/shm: %m");
- return -errno;
+ return log_warning_errno(errno, "Failed to read /proc/sysvipc/shm: %m");
}
}
-static int clean_sysvipc_sem(uid_t delete_uid) {
+static int clean_sysvipc_sem(uid_t delete_uid
, gid_t delete_gid
) {
_cleanup_fclose_ FILE *f = NULL;
char line[LINE_MAX];
bool first = true;
_cleanup_fclose_ FILE *f = NULL;
char line[LINE_MAX];
bool first = true;
@@
-101,8
+122,7
@@
static int clean_sysvipc_sem(uid_t delete_uid) {
if (errno == ENOENT)
return 0;
if (errno == ENOENT)
return 0;
- log_warning_errno(errno, "Failed to open /proc/sysvipc/sem: %m");
- return -errno;
+ return log_warning_errno(errno, "Failed to open /proc/sysvipc/sem: %m");
}
FOREACH_LINE(line, f, goto fail) {
}
FOREACH_LINE(line, f, goto fail) {
@@
-121,7
+141,7
@@
static int clean_sysvipc_sem(uid_t delete_uid) {
&semid, &uid, &gid, &cuid, &cgid) != 5)
continue;
&semid, &uid, &gid, &cuid, &cgid) != 5)
continue;
- if (
uid != delete_uid
)
+ if (
!match_uid_gid(uid, gid, delete_uid, delete_gid)
)
continue;
if (semctl(semid, 0, IPC_RMID) < 0) {
continue;
if (semctl(semid, 0, IPC_RMID) < 0) {
@@
-130,19
+150,20
@@
static int clean_sysvipc_sem(uid_t delete_uid) {
if (errno == EIDRM || errno == EINVAL)
continue;
if (errno == EIDRM || errno == EINVAL)
continue;
- log_warning_errno(errno, "Failed to remove SysV semaphores object %i: %m", semid);
- ret = -errno;
- }
+ ret = log_warning_errno(errno,
+ "Failed to remove SysV semaphores object %i: %m",
+ semid);
+ } else
+ log_debug("Removed SysV semaphore %i.", semid);
}
return ret;
fail:
}
return ret;
fail:
- log_warning_errno(errno, "Failed to read /proc/sysvipc/sem: %m");
- return -errno;
+ return log_warning_errno(errno, "Failed to read /proc/sysvipc/sem: %m");
}
}
-static int clean_sysvipc_msg(uid_t delete_uid) {
+static int clean_sysvipc_msg(uid_t delete_uid
, gid_t delete_gid
) {
_cleanup_fclose_ FILE *f = NULL;
char line[LINE_MAX];
bool first = true;
_cleanup_fclose_ FILE *f = NULL;
char line[LINE_MAX];
bool first = true;
@@
-153,8
+174,7
@@
static int clean_sysvipc_msg(uid_t delete_uid) {
if (errno == ENOENT)
return 0;
if (errno == ENOENT)
return 0;
- log_warning_errno(errno, "Failed to open /proc/sysvipc/msg: %m");
- return -errno;
+ return log_warning_errno(errno, "Failed to open /proc/sysvipc/msg: %m");
}
FOREACH_LINE(line, f, goto fail) {
}
FOREACH_LINE(line, f, goto fail) {
@@
-174,7
+194,7
@@
static int clean_sysvipc_msg(uid_t delete_uid) {
&msgid, &cpid, &lpid, &uid, &gid, &cuid, &cgid) != 7)
continue;
&msgid, &cpid, &lpid, &uid, &gid, &cuid, &cgid) != 7)
continue;
- if (
uid != delete_uid
)
+ if (
!match_uid_gid(uid, gid, delete_uid, delete_gid)
)
continue;
if (msgctl(msgid, IPC_RMID, NULL) < 0) {
continue;
if (msgctl(msgid, IPC_RMID, NULL) < 0) {
@@
-183,25
+203,26
@@
static int clean_sysvipc_msg(uid_t delete_uid) {
if (errno == EIDRM || errno == EINVAL)
continue;
if (errno == EIDRM || errno == EINVAL)
continue;
- log_warning_errno(errno, "Failed to remove SysV message queue %i: %m", msgid);
- ret = -errno;
- }
+ ret = log_warning_errno(errno,
+ "Failed to remove SysV message queue %i: %m",
+ msgid);
+ } else
+ log_debug("Removed SysV message queue %i.", msgid);
}
return ret;
fail:
}
return ret;
fail:
- log_warning_errno(errno, "Failed to read /proc/sysvipc/msg: %m");
- return -errno;
+ return log_warning_errno(errno, "Failed to read /proc/sysvipc/msg: %m");
}
}
-static int clean_posix_shm_internal(DIR *dir, uid_t uid) {
+static int clean_posix_shm_internal(DIR *dir, uid_t uid
, gid_t gid
) {
struct dirent *de;
int ret = 0, r;
assert(dir);
struct dirent *de;
int ret = 0, r;
assert(dir);
- FOREACH_DIRENT(de, dir, goto fail) {
+ FOREACH_DIRENT
_ALL
(de, dir, goto fail) {
struct stat st;
if (STR_IN_SET(de->d_name, "..", "."))
struct stat st;
if (STR_IN_SET(de->d_name, "..", "."))
@@
-211,12
+232,11
@@
static int clean_posix_shm_internal(DIR *dir, uid_t uid) {
if (errno == ENOENT)
continue;
if (errno == ENOENT)
continue;
- log_warning_errno(errno, "Failed to stat() POSIX shared memory segment %s: %m", de->d_name);
- ret = -errno;
+ ret = log_warning_errno(errno, "Failed to stat() POSIX shared memory segment %s: %m", de->d_name);
continue;
}
continue;
}
- if (
st.st_uid != uid
)
+ if (
!match_uid_gid(st.st_uid, st.st_gid, uid, gid)
)
continue;
if (S_ISDIR(st.st_mode)) {
continue;
if (S_ISDIR(st.st_mode)) {
@@
-224,12
+244,10
@@
static int clean_posix_shm_internal(DIR *dir, uid_t uid) {
kid = xopendirat(dirfd(dir), de->d_name, O_NOFOLLOW|O_NOATIME);
if (!kid) {
kid = xopendirat(dirfd(dir), de->d_name, O_NOFOLLOW|O_NOATIME);
if (!kid) {
- if (errno != ENOENT) {
- log_warning_errno(errno, "Failed to enter shared memory directory %s: %m", de->d_name);
- ret = -errno;
- }
+ if (errno != ENOENT)
+ ret = log_warning_errno(errno, "Failed to enter shared memory directory %s: %m", de->d_name);
} else {
} else {
- r = clean_posix_shm_internal(kid, uid);
+ r = clean_posix_shm_internal(kid, uid
, gid
);
if (r < 0)
ret = r;
}
if (r < 0)
ret = r;
}
@@
-239,9
+257,9
@@
static int clean_posix_shm_internal(DIR *dir, uid_t uid) {
if (errno == ENOENT)
continue;
if (errno == ENOENT)
continue;
- log_warning_errno(errno, "Failed to remove POSIX shared memory directory %s: %m", de->d_name);
- ret = -errno;
- }
+
ret =
log_warning_errno(errno, "Failed to remove POSIX shared memory directory %s: %m", de->d_name);
+ } else
+ log_debug("Removed POSIX shared memory directory %s", de->d_name);
} else {
if (unlinkat(dirfd(dir), de->d_name, 0) < 0) {
} else {
if (unlinkat(dirfd(dir), de->d_name, 0) < 0) {
@@
-249,20
+267,19
@@
static int clean_posix_shm_internal(DIR *dir, uid_t uid) {
if (errno == ENOENT)
continue;
if (errno == ENOENT)
continue;
- log_warning_errno(errno, "Failed to remove POSIX shared memory segment %s: %m", de->d_name);
- ret = -errno;
- }
+
ret =
log_warning_errno(errno, "Failed to remove POSIX shared memory segment %s: %m", de->d_name);
+ } else
+ log_debug("Removed POSIX shared memory segment %s", de->d_name);
}
}
return ret;
fail:
}
}
return ret;
fail:
- log_warning_errno(errno, "Failed to read /dev/shm: %m");
- return -errno;
+ return log_warning_errno(errno, "Failed to read /dev/shm: %m");
}
}
-static int clean_posix_shm(uid_t uid) {
+static int clean_posix_shm(uid_t uid
, gid_t gid
) {
_cleanup_closedir_ DIR *dir = NULL;
dir = opendir("/dev/shm");
_cleanup_closedir_ DIR *dir = NULL;
dir = opendir("/dev/shm");
@@
-270,16
+287,14
@@
static int clean_posix_shm(uid_t uid) {
if (errno == ENOENT)
return 0;
if (errno == ENOENT)
return 0;
- log_warning_errno(errno, "Failed to open /dev/shm: %m");
- return -errno;
+ return log_warning_errno(errno, "Failed to open /dev/shm: %m");
}
}
- return clean_posix_shm_internal(dir, uid);
+ return clean_posix_shm_internal(dir, uid
, gid
);
}
}
-/// UNNEEDED by elogind
-#if 0
-static int clean_posix_mq(uid_t uid) {
+#if 0 /// UNNEEDED by elogind
+static int clean_posix_mq(uid_t uid, gid_t gid) {
_cleanup_closedir_ DIR *dir = NULL;
struct dirent *de;
int ret = 0;
_cleanup_closedir_ DIR *dir = NULL;
struct dirent *de;
int ret = 0;
@@
-289,11
+304,10
@@
static int clean_posix_mq(uid_t uid) {
if (errno == ENOENT)
return 0;
if (errno == ENOENT)
return 0;
- log_warning_errno(errno, "Failed to open /dev/mqueue: %m");
- return -errno;
+ return log_warning_errno(errno, "Failed to open /dev/mqueue: %m");
}
}
- FOREACH_DIRENT(de, dir, goto fail) {
+ FOREACH_DIRENT
_ALL
(de, dir, goto fail) {
struct stat st;
char fn[1+strlen(de->d_name)+1];
struct stat st;
char fn[1+strlen(de->d_name)+1];
@@
-304,12
+318,13
@@
static int clean_posix_mq(uid_t uid) {
if (errno == ENOENT)
continue;
if (errno == ENOENT)
continue;
- log_warning_errno(errno, "Failed to stat() MQ segment %s: %m", de->d_name);
- ret = -errno;
+ ret = log_warning_errno(errno,
+ "Failed to stat() MQ segment %s: %m",
+ de->d_name);
continue;
}
continue;
}
- if (
st.st_uid != uid
)
+ if (
!match_uid_gid(st.st_uid, st.st_gid, uid, gid)
)
continue;
fn[0] = '/';
continue;
fn[0] = '/';
@@
-319,48
+334,62
@@
static int clean_posix_mq(uid_t uid) {
if (errno == ENOENT)
continue;
if (errno == ENOENT)
continue;
- log_warning_errno(errno, "Failed to unlink POSIX message queue %s: %m", fn);
- ret = -errno;
- }
+ ret = log_warning_errno(errno,
+ "Failed to unlink POSIX message queue %s: %m",
+ fn);
+ } else
+ log_debug("Removed POSIX message queue %s", fn);
}
return ret;
fail:
}
return ret;
fail:
- log_warning_errno(errno, "Failed to read /dev/mqueue: %m");
- return -errno;
+ return log_warning_errno(errno, "Failed to read /dev/mqueue: %m");
}
#endif // 0
}
#endif // 0
-int clean_ipc(uid_t uid) {
+int clean_ipc(uid_t uid
, gid_t gid
) {
int ret = 0, r;
int ret = 0, r;
- /*
Refuse to clean IPC of the root and system users
*/
- if (
uid <= SYSTEM_UID_MAX
)
+ /*
Anything to do?
*/
+ if (
!uid_is_valid(uid) && !gid_is_valid(gid)
)
return 0;
return 0;
- r = clean_sysvipc_shm(uid);
+ /* Refuse to clean IPC of the root user */
+ if (uid == 0 && gid == 0)
+ return 0;
+
+ r = clean_sysvipc_shm(uid, gid);
if (r < 0)
ret = r;
if (r < 0)
ret = r;
- r = clean_sysvipc_sem(uid);
+ r = clean_sysvipc_sem(uid
, gid
);
if (r < 0)
ret = r;
if (r < 0)
ret = r;
- r = clean_sysvipc_msg(uid);
+ r = clean_sysvipc_msg(uid
, gid
);
if (r < 0)
ret = r;
if (r < 0)
ret = r;
- r = clean_posix_shm(uid);
+ r = clean_posix_shm(uid
, gid
);
if (r < 0)
ret = r;
if (r < 0)
ret = r;
-/// elogind does not use mq_open anywhere
-#if 0
- r = clean_posix_mq(uid);
+#if 0 /// elogind does not use mq_open anywhere
+ r = clean_posix_mq(uid, gid);
if (r < 0)
ret = r;
#endif // 0
return ret;
}
if (r < 0)
ret = r;
#endif // 0
return ret;
}
+
+int clean_ipc_by_uid(uid_t uid) {
+ return clean_ipc(uid, GID_INVALID);
+}
+
+#if 0 /// UNNEEDED by elogind
+int clean_ipc_by_gid(gid_t gid) {
+ return clean_ipc(UID_INVALID, gid);
+}
+#endif // 0