![Lennart Poettering](/assets/img/avatar_default.png)
We currently use the ownership of the top-level directory as a hint whether we need to descent into the whole tree to chown() it recursively or not. This is problematic with the previous chown()ing algorithm, as when descending into the tree we'd first chown() and then descend further down, which meant that the top-level directory would be chowned first, and an aborted recursive chowning would appear on the next invocation as successful, even though it was not. Let's reshuffle things a bit, to make the re-chown()ing safe regarding interruptions: a) We chown() the dir we are looking at last, and descent into all its children first. That way we know that if the top-level dir is properly owned everything inside of it is properly owned too. b) Before starting a chown()ing operation, we mark the top-level directory as owned by a special "busy" UID range, which we can use to recognize whether a tree was fully chowned: if it is marked as busy, it's definitely not fully chowned, as the busy ownership will only be fixed as final step of the chowning. Fixes: #6292
34 lines
1.4 KiB
C
34 lines
1.4 KiB
C
#pragma once
|
|
|
|
/***
|
|
This file is part of systemd.
|
|
|
|
Copyright 2017 Lennart Poettering
|
|
|
|
systemd is free software; you can redistribute it and/or modify it
|
|
under the terms of the GNU Lesser General Public License as published by
|
|
the Free Software Foundation; either version 2.1 of the License, or
|
|
(at your option) any later version.
|
|
|
|
systemd is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
|
***/
|
|
|
|
#include <sys/types.h>
|
|
|
|
/* Note that devpts's gid= parameter parses GIDs as signed values, hence we stay away from the upper half of the 32bit
|
|
* UID range here. We leave a bit of room at the lower end and a lot of room at the upper end, so that other subsystems
|
|
* may have their own allocation ranges too. */
|
|
#define UID_SHIFT_PICK_MIN ((uid_t) UINT32_C(0x00080000))
|
|
#define UID_SHIFT_PICK_MAX ((uid_t) UINT32_C(0x6FFF0000))
|
|
|
|
/* While we are chmod()ing a directory tree, we set the top-level UID base to this "busy" base, so that we can always
|
|
* recognize trees we are were chmod()ing recursively and got interrupted in */
|
|
#define UID_BUSY_BASE ((uid_t) UINT32_C(0xFFFE0000))
|
|
#define UID_BUSY_MASK ((uid_t) UINT32_C(0xFFFF0000))
|