Accepting request 668288 from Base:System
- btrfs-subvolumes.patch: implement support for creating user home directories on btrfs subvolumes (fate#316134) Additionally changed in that patch (bsc#1106914): OBS-URL: https://build.opensuse.org/request/show/668288 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/shadow?expand=0&rev=29
This commit is contained in:
commit
33c20f12fb
318
btrfs-subvolumes.patch
Normal file
318
btrfs-subvolumes.patch
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
commit 52ea836ffbfa4d6797cf89d6ada58f76bee9cf6b
|
||||||
|
Author: Adam Majer <amajer@suse.de>
|
||||||
|
Date: Wed Jan 23 16:17:05 2019 +0100
|
||||||
|
|
||||||
|
Add autotools support for BtrFS option
|
||||||
|
|
||||||
|
Feature is enabled by default, if headers are available. It can be
|
||||||
|
turned off explictly.
|
||||||
|
|
||||||
|
commit 81ead2042afcdb8d423da855cf1528618a4e0c01
|
||||||
|
Author: Adam Majer <amajer@suse.de>
|
||||||
|
Date: Mon Jan 21 09:32:36 2019 +0100
|
||||||
|
|
||||||
|
Add support for btrfs subvolumes for user homes
|
||||||
|
|
||||||
|
new switch added to useradd command, --btrfs-subvolume-home. When
|
||||||
|
specified *and* the filesystem is detected as btrfs, it will create a
|
||||||
|
subvolume for user's home instead of a plain directory. This is done via
|
||||||
|
`btrfs subvolume` command. Specifying the new switch while trying to
|
||||||
|
create home on non-btrfs will result in an error.
|
||||||
|
|
||||||
|
userdel -r will handle and remove this subvolume transparently via
|
||||||
|
`btrfs subvolume` command. Previosuly this failed as you can't rmdir a
|
||||||
|
subvolume.
|
||||||
|
|
||||||
|
usermod, when moving user's home across devices, will detect if the home
|
||||||
|
is a subvolume and issue an error messages instead of copying it. Moving
|
||||||
|
user's home (as subvolume) on same btrfs works transparently.
|
||||||
|
|
||||||
|
|
||||||
|
--- a/configure.ac
|
||||||
|
+++ b/configure.ac
|
||||||
|
@@ -256,6 +256,9 @@ AC_ARG_WITH(audit,
|
||||||
|
AC_ARG_WITH(libpam,
|
||||||
|
[AC_HELP_STRING([--with-libpam], [use libpam for PAM support @<:@default=yes if found@:>@])],
|
||||||
|
[with_libpam=$withval], [with_libpam=maybe])
|
||||||
|
+AC_ARG_WITH(btrfs,
|
||||||
|
+ [AC_HELP_STRING([--with-btrfs], [add BtrFS support @<:@default=yes if found@:>@])],
|
||||||
|
+ [with_selinux=$withval], [with_selinux=maybe])
|
||||||
|
AC_ARG_WITH(selinux,
|
||||||
|
[AC_HELP_STRING([--with-selinux], [use SELinux support @<:@default=yes if found@:>@])],
|
||||||
|
[with_selinux=$withval], [with_selinux=maybe])
|
||||||
|
@@ -453,6 +456,20 @@ if test "$with_libcrack" = "yes"; then
|
||||||
|
AC_DEFINE(HAVE_LIBCRACK_PW, 1, [Defined if it includes *Pw functions.]))
|
||||||
|
fi
|
||||||
|
|
||||||
|
+if test "$with_btrfs" != "no"; then
|
||||||
|
+ AC_CHECK_HEADERS([sys/statfs.h linux/magic.h linux/btrfs_tree.h], \
|
||||||
|
+ [btrfs_headers="yes"], [btrfs_headers="no"])
|
||||||
|
+ if test "$btrfs_headers$with_btrfs" = "noyes" ; then
|
||||||
|
+ AC_MSG_ERROR([One of sys/statfs.h linux/magic.h linux/btrfs_tree.h is missing])
|
||||||
|
+ fi
|
||||||
|
+
|
||||||
|
+ if test "$btrfs_headers" = "yes" ; then
|
||||||
|
+ AC_DEFINE(WITH_BTRFS, 1, [Build shadow with BtrFS support])
|
||||||
|
+ with_btrfs="yes"
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+AM_CONDITIONAL(WITH_BTRFS, test x$with_btrfs = xyes)
|
||||||
|
+
|
||||||
|
AC_SUBST(LIBSELINUX)
|
||||||
|
AC_SUBST(LIBSEMANAGE)
|
||||||
|
if test "$with_selinux" != "no"; then
|
||||||
|
@@ -672,6 +689,7 @@ if test "$with_libpam" = "yes"; then
|
||||||
|
echo " suid account management tools: $enable_acct_tools_setuid"
|
||||||
|
fi
|
||||||
|
echo " SELinux support: $with_selinux"
|
||||||
|
+echo " BtrFS support: $with_btrfs"
|
||||||
|
echo " ACL support: $with_acl"
|
||||||
|
echo " Extended Attributes support: $with_attr"
|
||||||
|
echo " tcb support (incomplete): $with_tcb"
|
||||||
|
--- a/lib/prototypes.h
|
||||||
|
+++ b/lib/prototypes.h
|
||||||
|
@@ -72,6 +72,14 @@ extern int expire (const struct passwd *
|
||||||
|
/* isexpired.c */
|
||||||
|
extern int isexpired (const struct passwd *, /*@null@*/const struct spwd *);
|
||||||
|
|
||||||
|
+/* btrfs.c */
|
||||||
|
+#ifdef WITH_BTRFS
|
||||||
|
+extern int btrfs_create_subvolume(const char *path);
|
||||||
|
+extern int btrfs_remove_subvolume(const char *path);
|
||||||
|
+extern int btrfs_is_subvolume(const char *path);
|
||||||
|
+extern int is_btrfs(const char *path);
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/* basename() renamed to Basename() to avoid libc name space confusion */
|
||||||
|
/* basename.c */
|
||||||
|
extern /*@observer@*/const char *Basename (const char *str);
|
||||||
|
--- a/libmisc/Makefile.am
|
||||||
|
+++ b/libmisc/Makefile.am
|
||||||
|
@@ -72,3 +72,8 @@ libmisc_a_SOURCES = \
|
||||||
|
xgetspnam.c \
|
||||||
|
xmalloc.c \
|
||||||
|
yesno.c
|
||||||
|
+
|
||||||
|
+if WITH_BTRFS
|
||||||
|
+libmisc_a_SOURCES += btrfs.c
|
||||||
|
+endif
|
||||||
|
+
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/libmisc/btrfs.c
|
||||||
|
@@ -0,0 +1,94 @@
|
||||||
|
+#include <linux/btrfs_tree.h>
|
||||||
|
+#include <linux/magic.h>
|
||||||
|
+#include <sys/statfs.h>
|
||||||
|
+
|
||||||
|
+#include "prototypes.h"
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static int run_btrfs_subvolume_cmd(const char *subcmd, const char *arg1, const char *arg2)
|
||||||
|
+{
|
||||||
|
+ int status = 0;
|
||||||
|
+ const char *cmd = "/sbin/btrfs";
|
||||||
|
+ const char *argv[] = {
|
||||||
|
+ strrchr(cmd, '/'),
|
||||||
|
+ "subvolume",
|
||||||
|
+ subcmd,
|
||||||
|
+ arg1,
|
||||||
|
+ arg2,
|
||||||
|
+ NULL
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ if (argv[0] == NULL)
|
||||||
|
+ argv[0] = cmd;
|
||||||
|
+ else
|
||||||
|
+ argv[0] = argv[0] + 1;
|
||||||
|
+
|
||||||
|
+ if (access(cmd, X_OK)) {
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (run_command(cmd, argv, NULL, &status))
|
||||||
|
+ return -1;
|
||||||
|
+ return status;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+int btrfs_create_subvolume(const char *path)
|
||||||
|
+{
|
||||||
|
+ return run_btrfs_subvolume_cmd("create", path, NULL);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+int btrfs_remove_subvolume(const char *path)
|
||||||
|
+{
|
||||||
|
+ return run_btrfs_subvolume_cmd("delete", "-C", path);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/* Adapted from btrfsprogs */
|
||||||
|
+/*
|
||||||
|
+ * This intentionally duplicates btrfs_util_is_subvolume_fd() instead of opening
|
||||||
|
+ * a file descriptor and calling it, because fstat() and fstatfs() don't accept
|
||||||
|
+ * file descriptors opened with O_PATH on old kernels (before v3.6 and before
|
||||||
|
+ * v3.12, respectively), but stat() and statfs() can be called on a path that
|
||||||
|
+ * the user doesn't have read or write permissions to.
|
||||||
|
+ *
|
||||||
|
+ * returns:
|
||||||
|
+ * 1 - btrfs subvolume
|
||||||
|
+ * 0 - not btrfs subvolume
|
||||||
|
+ * -1 - error
|
||||||
|
+ */
|
||||||
|
+int btrfs_is_subvolume(const char *path)
|
||||||
|
+{
|
||||||
|
+ struct stat st;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = is_btrfs(path);
|
||||||
|
+ if (ret <= 0)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ ret = stat(path, &st);
|
||||||
|
+ if (ret == -1)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ if (st.st_ino != BTRFS_FIRST_FREE_OBJECTID || !S_ISDIR(st.st_mode)) {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/* Adapted from btrfsprogs */
|
||||||
|
+int is_btrfs(const char *path)
|
||||||
|
+{
|
||||||
|
+ struct statfs sfs;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = statfs(path, &sfs);
|
||||||
|
+ if (ret == -1)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ return sfs.f_type == BTRFS_SUPER_MAGIC;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
--- a/src/useradd.c
|
||||||
|
+++ b/src/useradd.c
|
||||||
|
@@ -164,6 +164,7 @@ static bool
|
||||||
|
oflg = false, /* permit non-unique user ID to be specified with -u */
|
||||||
|
rflg = false, /* create a system account */
|
||||||
|
sflg = false, /* shell program for new account */
|
||||||
|
+ subvolflg = false, /* create subvolume home on BTRFS */
|
||||||
|
uflg = false, /* specify user ID for new account */
|
||||||
|
Uflg = false; /* create a group having the same name as the user */
|
||||||
|
|
||||||
|
@@ -805,6 +806,9 @@ static void usage (int status)
|
||||||
|
Prog, Prog, Prog);
|
||||||
|
(void) fputs (_(" -b, --base-dir BASE_DIR base directory for the home directory of the\n"
|
||||||
|
" new account\n"), usageout);
|
||||||
|
+#ifdef WITH_BTRFS
|
||||||
|
+ (void) fputs (_(" --btrfs-subvolume-home use BTRFS subvolume for home directory\n"), usageout);
|
||||||
|
+#endif
|
||||||
|
(void) fputs (_(" -c, --comment COMMENT GECOS field of the new account\n"), usageout);
|
||||||
|
(void) fputs (_(" -d, --home-dir HOME_DIR home directory of the new account\n"), usageout);
|
||||||
|
(void) fputs (_(" -D, --defaults print or change default useradd configuration\n"), usageout);
|
||||||
|
@@ -1085,6 +1089,9 @@ static void process_flags (int argc, cha
|
||||||
|
int c;
|
||||||
|
static struct option long_options[] = {
|
||||||
|
{"base-dir", required_argument, NULL, 'b'},
|
||||||
|
+#ifdef WITH_BTRFS
|
||||||
|
+ {"btrfs-subvolume-home", no_argument, NULL, 200},
|
||||||
|
+#endif
|
||||||
|
{"comment", required_argument, NULL, 'c'},
|
||||||
|
{"home-dir", required_argument, NULL, 'd'},
|
||||||
|
{"defaults", no_argument, NULL, 'D'},
|
||||||
|
@@ -1131,6 +1138,9 @@ static void process_flags (int argc, cha
|
||||||
|
def_home = optarg;
|
||||||
|
bflg = true;
|
||||||
|
break;
|
||||||
|
+ case 200:
|
||||||
|
+ subvolflg = true;
|
||||||
|
+ break;
|
||||||
|
case 'c':
|
||||||
|
if (!VALID (optarg)) {
|
||||||
|
fprintf (stderr,
|
||||||
|
@@ -2049,6 +2059,37 @@ static void create_home (void)
|
||||||
|
strcat (path, "/");
|
||||||
|
strcat (path, cp);
|
||||||
|
if (access (path, F_OK) != 0) {
|
||||||
|
+ /* Check if parent directory is BTRFS, fail if requesting
|
||||||
|
+ subvolume but no BTRFS. The paths cound be different by the
|
||||||
|
+ trailing slash
|
||||||
|
+ */
|
||||||
|
+#if WITH_BTRFS
|
||||||
|
+ if (subvolflg && (strlen(prefix_user_home) - (int)strlen(path)) <= 1) {
|
||||||
|
+ char *btrfs_check = strdup(path);
|
||||||
|
+
|
||||||
|
+ if (!btrfs_check) {
|
||||||
|
+ fprintf (stderr,
|
||||||
|
+ _("%s: error while duplicating string in BTRFS check %s\n"),
|
||||||
|
+ Prog, path);
|
||||||
|
+ fail_exit (E_HOMEDIR);
|
||||||
|
+ }
|
||||||
|
+ btrfs_check[strlen(path) - strlen(cp) - 1] = '\0';
|
||||||
|
+ if (is_btrfs(btrfs_check) <= 0) {
|
||||||
|
+ fprintf (stderr,
|
||||||
|
+ _("%s: home directory \"%s\" must be mounted on BTRFS\n"),
|
||||||
|
+ Prog, path);
|
||||||
|
+ fail_exit (E_HOMEDIR);
|
||||||
|
+ }
|
||||||
|
+ // make subvolume to mount for user instead of directory
|
||||||
|
+ if (btrfs_create_subvolume(path)) {
|
||||||
|
+ fprintf (stderr,
|
||||||
|
+ _("%s: failed to create BTRFS subvolume: %s\n"),
|
||||||
|
+ Prog, path);
|
||||||
|
+ fail_exit (E_HOMEDIR);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+#endif
|
||||||
|
if (mkdir (path, 0) != 0) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: cannot create directory %s\n"),
|
||||||
|
--- a/src/userdel.c
|
||||||
|
+++ b/src/userdel.c
|
||||||
|
@@ -1273,6 +1273,23 @@ int main (int argc, char **argv)
|
||||||
|
#endif /* EXTRA_CHECK_HOME_DIR */
|
||||||
|
|
||||||
|
if (rflg) {
|
||||||
|
+#ifdef WITH_BTRFS
|
||||||
|
+ int is_subvolume = btrfs_is_subvolume (user_home);
|
||||||
|
+ if (is_subvolume < 0) {
|
||||||
|
+ errors++;
|
||||||
|
+ /* continue */
|
||||||
|
+ }
|
||||||
|
+ else if (is_subvolume > 0) {
|
||||||
|
+ if (btrfs_remove_subvolume (user_home)) {
|
||||||
|
+ fprintf (stderr,
|
||||||
|
+ _("%s: error removing subvolume %s\n"),
|
||||||
|
+ Prog, user_home);
|
||||||
|
+ errors++;
|
||||||
|
+ /* continue */
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ else
|
||||||
|
+#endif
|
||||||
|
if (remove_tree (user_home, true) != 0) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: error removing directory %s\n"),
|
||||||
|
--- a/src/usermod.c
|
||||||
|
+++ b/src/usermod.c
|
||||||
|
@@ -1818,6 +1818,15 @@ static void move_home (void)
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (EXDEV == errno) {
|
||||||
|
+#ifdef WITH_BTRFS
|
||||||
|
+ if (btrfs_is_subvolume (prefix_user_home) > 0) {
|
||||||
|
+ fprintf (stderr,
|
||||||
|
+ _("%s: error: cannot move subvolume from %s to %s - different device\n"),
|
||||||
|
+ Prog, prefix_user_home, prefix_user_newhome);
|
||||||
|
+ fail_exit (E_HOMEDIR);
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
if (copy_tree (prefix_user_home, prefix_user_newhome, true,
|
||||||
|
true,
|
||||||
|
user_id,
|
@ -1,3 +1,9 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Jan 23 09:35:01 UTC 2019 - adam.majer@suse.de
|
||||||
|
|
||||||
|
- btrfs-subvolumes.patch: implement support for creating user home
|
||||||
|
directories on btrfs subvolumes (fate#316134)
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Wed Oct 31 14:17:29 UTC 2018 - Valentin Rothberg <vrothberg@suse.com>
|
Wed Oct 31 14:17:29 UTC 2018 - Valentin Rothberg <vrothberg@suse.com>
|
||||||
|
|
||||||
@ -25,7 +31,7 @@ Mon May 14 12:45:42 UTC 2018 - mvetter@suse.com
|
|||||||
- Remove shadow-4.1.5.1-pam_group.patch: upstreamed
|
- Remove shadow-4.1.5.1-pam_group.patch: upstreamed
|
||||||
- Update userdel-script.patch: change due to prefix
|
- Update userdel-script.patch: change due to prefix
|
||||||
- Update useradd-mkdirs.patch: change due to prefix
|
- Update useradd-mkdirs.patch: change due to prefix
|
||||||
Additionally changed in that patch:
|
Additionally changed in that patch (bsc#1106914):
|
||||||
* Test for strdup() failure
|
* Test for strdup() failure
|
||||||
* Directory to 0755 instead 0777
|
* Directory to 0755 instead 0777
|
||||||
- Add shadow-4.6.0-fix-usermod-prefix-crash.patch:
|
- Add shadow-4.6.0-fix-usermod-prefix-crash.patch:
|
||||||
|
10
shadow.spec
10
shadow.spec
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# spec file for package shadow
|
# spec file for package shadow
|
||||||
#
|
#
|
||||||
# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
|
# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
|
||||||
#
|
#
|
||||||
# All modifications and additions to the file contributed by third parties
|
# All modifications and additions to the file contributed by third parties
|
||||||
# remain the property of their copyright owners, unless otherwise agreed
|
# remain the property of their copyright owners, unless otherwise agreed
|
||||||
@ -12,7 +12,7 @@
|
|||||||
# license that conforms to the Open Source Definition (Version 1.9)
|
# license that conforms to the Open Source Definition (Version 1.9)
|
||||||
# published by the Open Source Initiative.
|
# published by the Open Source Initiative.
|
||||||
|
|
||||||
# Please submit bugfixes or comments via https://bugs.opensuse.org/
|
# Please submit bugfixes or comments via http://bugs.opensuse.org/
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
@ -45,11 +45,15 @@ Patch10: encryption_method_nis.patch
|
|||||||
Patch11: useradd-mkdirs.patch
|
Patch11: useradd-mkdirs.patch
|
||||||
Patch12: shadow-4.6.0-fix-usermod-prefix-crash.patch
|
Patch12: shadow-4.6.0-fix-usermod-prefix-crash.patch
|
||||||
Patch20: disable_new_audit_function.patch
|
Patch20: disable_new_audit_function.patch
|
||||||
|
Patch21: btrfs-subvolumes.patch
|
||||||
BuildRequires: audit-devel > 2.3
|
BuildRequires: audit-devel > 2.3
|
||||||
|
BuildRequires: autoconf
|
||||||
|
BuildRequires: automake
|
||||||
BuildRequires: libacl-devel
|
BuildRequires: libacl-devel
|
||||||
BuildRequires: libattr-devel
|
BuildRequires: libattr-devel
|
||||||
BuildRequires: libselinux-devel
|
BuildRequires: libselinux-devel
|
||||||
BuildRequires: libsemanage-devel
|
BuildRequires: libsemanage-devel
|
||||||
|
BuildRequires: libtool
|
||||||
BuildRequires: pam-devel
|
BuildRequires: pam-devel
|
||||||
BuildRequires: xz
|
BuildRequires: xz
|
||||||
Requires(pre): group(root)
|
Requires(pre): group(root)
|
||||||
@ -80,6 +84,7 @@ group accounts.
|
|||||||
%if 0%{?suse_version} < 1330
|
%if 0%{?suse_version} < 1330
|
||||||
%patch20 -p1
|
%patch20 -p1
|
||||||
%endif
|
%endif
|
||||||
|
%patch21 -p1
|
||||||
|
|
||||||
iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8
|
iconv -f ISO88591 -t utf-8 doc/HOWTO > doc/HOWTO.utf8
|
||||||
mv -v doc/HOWTO.utf8 doc/HOWTO
|
mv -v doc/HOWTO.utf8 doc/HOWTO
|
||||||
@ -88,6 +93,7 @@ mv -v doc/HOWTO.utf8 doc/HOWTO
|
|||||||
export CFLAGS="%{optflags} -fpie"
|
export CFLAGS="%{optflags} -fpie"
|
||||||
export LDFLAGS="-pie"
|
export LDFLAGS="-pie"
|
||||||
|
|
||||||
|
autoreconf -fvi
|
||||||
%configure \
|
%configure \
|
||||||
--disable-shadowgrp \
|
--disable-shadowgrp \
|
||||||
--enable-account-tools-setuid \
|
--enable-account-tools-setuid \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user