]>
git.proxmox.com Git - systemd.git/blob - src/shared/clean-ipc.c
2 This file is part of systemd.
4 Copyright 2014 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
35 #include "clean-ipc.h"
36 #include "dirent-util.h"
39 #include "formats-util.h"
42 #include "string-util.h"
45 static int clean_sysvipc_shm(uid_t delete_uid
) {
46 _cleanup_fclose_
FILE *f
= NULL
;
51 f
= fopen("/proc/sysvipc/shm", "re");
56 return log_warning_errno(errno
, "Failed to open /proc/sysvipc/shm: %m");
59 FOREACH_LINE(line
, f
, goto fail
) {
73 if (sscanf(line
, "%*i %i %*o %*u " PID_FMT
" " PID_FMT
" %u " UID_FMT
" " GID_FMT
" " UID_FMT
" " GID_FMT
,
74 &shmid
, &cpid
, &lpid
, &n_attached
, &uid
, &gid
, &cuid
, &cgid
) != 8)
80 if (uid
!= delete_uid
)
83 if (shmctl(shmid
, IPC_RMID
, NULL
) < 0) {
85 /* Ignore entries that are already deleted */
86 if (errno
== EIDRM
|| errno
== EINVAL
)
89 ret
= log_warning_errno(errno
,
90 "Failed to remove SysV shared memory segment %i: %m",
98 return log_warning_errno(errno
, "Failed to read /proc/sysvipc/shm: %m");
101 static int clean_sysvipc_sem(uid_t delete_uid
) {
102 _cleanup_fclose_
FILE *f
= NULL
;
107 f
= fopen("/proc/sysvipc/sem", "re");
112 return log_warning_errno(errno
, "Failed to open /proc/sysvipc/sem: %m");
115 FOREACH_LINE(line
, f
, goto fail
) {
127 if (sscanf(line
, "%*i %i %*o %*u " UID_FMT
" " GID_FMT
" " UID_FMT
" " GID_FMT
,
128 &semid
, &uid
, &gid
, &cuid
, &cgid
) != 5)
131 if (uid
!= delete_uid
)
134 if (semctl(semid
, 0, IPC_RMID
) < 0) {
136 /* Ignore entries that are already deleted */
137 if (errno
== EIDRM
|| errno
== EINVAL
)
140 ret
= log_warning_errno(errno
,
141 "Failed to remove SysV semaphores object %i: %m",
149 return log_warning_errno(errno
, "Failed to read /proc/sysvipc/sem: %m");
152 static int clean_sysvipc_msg(uid_t delete_uid
) {
153 _cleanup_fclose_
FILE *f
= NULL
;
158 f
= fopen("/proc/sysvipc/msg", "re");
163 return log_warning_errno(errno
, "Failed to open /proc/sysvipc/msg: %m");
166 FOREACH_LINE(line
, f
, goto fail
) {
179 if (sscanf(line
, "%*i %i %*o %*u %*u " PID_FMT
" " PID_FMT
" " UID_FMT
" " GID_FMT
" " UID_FMT
" " GID_FMT
,
180 &msgid
, &cpid
, &lpid
, &uid
, &gid
, &cuid
, &cgid
) != 7)
183 if (uid
!= delete_uid
)
186 if (msgctl(msgid
, IPC_RMID
, NULL
) < 0) {
188 /* Ignore entries that are already deleted */
189 if (errno
== EIDRM
|| errno
== EINVAL
)
192 ret
= log_warning_errno(errno
,
193 "Failed to remove SysV message queue %i: %m",
201 return log_warning_errno(errno
, "Failed to read /proc/sysvipc/msg: %m");
204 static int clean_posix_shm_internal(DIR *dir
, uid_t uid
) {
210 FOREACH_DIRENT(de
, dir
, goto fail
) {
213 if (STR_IN_SET(de
->d_name
, "..", "."))
216 if (fstatat(dirfd(dir
), de
->d_name
, &st
, AT_SYMLINK_NOFOLLOW
) < 0) {
220 log_warning_errno(errno
, "Failed to stat() POSIX shared memory segment %s: %m", de
->d_name
);
225 if (st
.st_uid
!= uid
)
228 if (S_ISDIR(st
.st_mode
)) {
229 _cleanup_closedir_
DIR *kid
;
231 kid
= xopendirat(dirfd(dir
), de
->d_name
, O_NOFOLLOW
|O_NOATIME
);
233 if (errno
!= ENOENT
) {
234 log_warning_errno(errno
, "Failed to enter shared memory directory %s: %m", de
->d_name
);
238 r
= clean_posix_shm_internal(kid
, uid
);
243 if (unlinkat(dirfd(dir
), de
->d_name
, AT_REMOVEDIR
) < 0) {
248 log_warning_errno(errno
, "Failed to remove POSIX shared memory directory %s: %m", de
->d_name
);
253 if (unlinkat(dirfd(dir
), de
->d_name
, 0) < 0) {
258 log_warning_errno(errno
, "Failed to remove POSIX shared memory segment %s: %m", de
->d_name
);
267 log_warning_errno(errno
, "Failed to read /dev/shm: %m");
271 static int clean_posix_shm(uid_t uid
) {
272 _cleanup_closedir_
DIR *dir
= NULL
;
274 dir
= opendir("/dev/shm");
279 return log_warning_errno(errno
, "Failed to open /dev/shm: %m");
282 return clean_posix_shm_internal(dir
, uid
);
285 static int clean_posix_mq(uid_t uid
) {
286 _cleanup_closedir_
DIR *dir
= NULL
;
290 dir
= opendir("/dev/mqueue");
295 return log_warning_errno(errno
, "Failed to open /dev/mqueue: %m");
298 FOREACH_DIRENT(de
, dir
, goto fail
) {
300 char fn
[1+strlen(de
->d_name
)+1];
302 if (STR_IN_SET(de
->d_name
, "..", "."))
305 if (fstatat(dirfd(dir
), de
->d_name
, &st
, AT_SYMLINK_NOFOLLOW
) < 0) {
309 ret
= log_warning_errno(errno
,
310 "Failed to stat() MQ segment %s: %m",
315 if (st
.st_uid
!= uid
)
319 strcpy(fn
+1, de
->d_name
);
321 if (mq_unlink(fn
) < 0) {
325 ret
= log_warning_errno(errno
,
326 "Failed to unlink POSIX message queue %s: %m",
334 return log_warning_errno(errno
, "Failed to read /dev/mqueue: %m");
337 int clean_ipc(uid_t uid
) {
340 /* Refuse to clean IPC of the root and system users */
341 if (uid
<= SYSTEM_UID_MAX
)
344 r
= clean_sysvipc_shm(uid
);
348 r
= clean_sysvipc_sem(uid
);
352 r
= clean_sysvipc_msg(uid
);
356 r
= clean_posix_shm(uid
);
360 r
= clean_posix_mq(uid
);