Compare commits
10 Commits
5b2137797c
...
cb3d588aab
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb3d588aab | ||
|
|
5d22cefb4a | ||
|
|
a39ac0857e | ||
|
|
40d22c3533 | ||
|
|
e87e6f3ee4 | ||
|
|
cca2696f61 | ||
|
|
1672323b04 | ||
|
|
69dfb82329 | ||
|
|
63fe17d2e5 | ||
|
|
924aeaf613 |
@ -0,0 +1,29 @@
|
|||||||
|
From eaebea55a495a56317ed85e959b3599f73c6bdf2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: David Michael <fedora.dm0@gmail.com>
|
||||||
|
Date: Sun, 23 Oct 2022 18:51:33 -0400
|
||||||
|
Subject: [PATCH] useradd: Fix buffer overflow when using a prefix
|
||||||
|
|
||||||
|
The buffer length did not count the string's trailing null byte.
|
||||||
|
|
||||||
|
Signed-off-by: David Michael <fedora.dm0@gmail.com>
|
||||||
|
|
||||||
|
Conflict: if(prefix[0]) There is no space after it.
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/f6f8bcd2a57c06983296485cc028ebdf467ebfd7
|
||||||
|
|
||||||
|
---
|
||||||
|
src/useradd.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/useradd.c b/src/useradd.c
|
||||||
|
index 39a744ee0..7ea0a9c4d 100644
|
||||||
|
--- a/src/useradd.c
|
||||||
|
+++ b/src/useradd.c
|
||||||
|
@@ -2372,7 +2372,7 @@ static void create_mail (void)
|
||||||
|
if (NULL == spool) {
|
||||||
|
spool = "/var/mail";
|
||||||
|
}
|
||||||
|
- file = alloca (strlen (prefix) + strlen (spool) + strlen (user_name) + 2);
|
||||||
|
+ file = alloca (strlen (prefix) + strlen (spool) + strlen (user_name) + 3);
|
||||||
|
if(prefix[0])
|
||||||
|
sprintf (file, "%s/%s/%s", prefix, spool, user_name);
|
||||||
|
else
|
||||||
28
backport-Added-documentation-around-CREATE_MAIL_SPOOL.patch
Normal file
28
backport-Added-documentation-around-CREATE_MAIL_SPOOL.patch
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
From aff4989d1acf3afc718813144658c295d8d10f20 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Andy Zaugg <andy.zaugg@gmail.com>
|
||||||
|
Date: Mon, 20 Sep 2021 20:41:50 -0700
|
||||||
|
Subject: [PATCH] Added documentation around CREATE_MAIL_SPOOL
|
||||||
|
|
||||||
|
Adding documentation aroud the parameter CREATE_MAIL_SPOOL in the
|
||||||
|
/etc/default/useradd file
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/aff4989d1acf3afc718813144658c295d8d10f20
|
||||||
|
|
||||||
|
---
|
||||||
|
man/login.defs.d/MAIL_DIR.xml | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/man/login.defs.d/MAIL_DIR.xml b/man/login.defs.d/MAIL_DIR.xml
|
||||||
|
index 60b82d6b1..b5adb888b 100644
|
||||||
|
--- a/man/login.defs.d/MAIL_DIR.xml
|
||||||
|
+++ b/man/login.defs.d/MAIL_DIR.xml
|
||||||
|
@@ -35,6 +35,8 @@
|
||||||
|
The mail spool directory. This is needed to manipulate the mailbox
|
||||||
|
when its corresponding user account is modified or deleted. If not
|
||||||
|
specified, a compile-time default is used.
|
||||||
|
+ The parameter CREATE_MAIL_SPOOL in <filename>/etc/default/useradd</filename>
|
||||||
|
+ determines whether the mail spool should be created.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry><varlistentry>
|
||||||
46
backport-Address-minor-compiler-warnings.patch
Normal file
46
backport-Address-minor-compiler-warnings.patch
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
From 6cbec2d0aa29d6d25e9eed007ded4e79eb637519 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
|
||||||
|
Date: Fri, 5 Aug 2022 17:57:29 +0200
|
||||||
|
Subject: [PATCH] Address minor compiler warnings
|
||||||
|
|
||||||
|
copydir.c:666:44: warning: unsigned conversion from 'int' to '__mode_t' {aka 'unsigned int'} changes value from '-4096' to '4294963200' [-Wsign-conversion]
|
||||||
|
666 | if ( (mknod (dst, statp->st_mode & ~07777, statp->st_rdev) != 0)
|
||||||
|
| ^
|
||||||
|
|
||||||
|
copydir.c:116:1: warning: missing initializer for field 'quote' of 'struct error_context' [-Wmissing-field-initializers]
|
||||||
|
116 | };
|
||||||
|
| ^
|
||||||
|
In file included from copydir.c:27:
|
||||||
|
/usr/include/attr/error_context.h:30:23: note: 'quote' declared here
|
||||||
|
30 | const char *(*quote) (struct error_context *, const char *);
|
||||||
|
| ^~~~~
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/6cbec2d0aa29d6d25e9eed007ded4e79eb637519
|
||||||
|
|
||||||
|
---
|
||||||
|
libmisc/copydir.c | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmisc/copydir.c b/libmisc/copydir.c
|
||||||
|
index 95042187b..e753d7cf0 100644
|
||||||
|
--- a/libmisc/copydir.c
|
||||||
|
+++ b/libmisc/copydir.c
|
||||||
|
@@ -112,7 +112,7 @@ static void error_acl (unused struct error_context *ctx, const char *fmt, ...)
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct error_context ctx = {
|
||||||
|
- error_acl
|
||||||
|
+ error_acl, NULL, NULL
|
||||||
|
};
|
||||||
|
#endif /* WITH_ACL || WITH_ATTR */
|
||||||
|
|
||||||
|
@@ -663,7 +663,7 @@ static int copy_special (const char *src, const char *dst,
|
||||||
|
}
|
||||||
|
#endif /* WITH_SELINUX */
|
||||||
|
|
||||||
|
- if ( (mknod (dst, statp->st_mode & ~07777, statp->st_rdev) != 0)
|
||||||
|
+ if ( (mknod (dst, statp->st_mode & ~07777U, statp->st_rdev) != 0)
|
||||||
|
|| (chown_if_needed (dst, statp,
|
||||||
|
old_uid, new_uid, old_gid, new_gid) != 0)
|
||||||
|
#ifdef WITH_ACL
|
||||||
228
backport-Avoid-races-in-chown_tree.patch
Normal file
228
backport-Avoid-races-in-chown_tree.patch
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
From e9ae247cb14f977d8881f481488843b10665dba8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
|
||||||
|
Date: Fri, 5 Aug 2022 17:57:19 +0200
|
||||||
|
Subject: [PATCH] Avoid races in chown_tree()
|
||||||
|
|
||||||
|
Use *at() functions to pin the directory operating in to avoid being
|
||||||
|
redirected by unprivileged users replacing parts of paths by symlinks to
|
||||||
|
privileged files.
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/e9ae247cb14f977d8881f481488843b10665dba8
|
||||||
|
|
||||||
|
---
|
||||||
|
libmisc/chowndir.c | 130 +++++++++++++++++----------------------------
|
||||||
|
1 file changed, 49 insertions(+), 81 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmisc/chowndir.c b/libmisc/chowndir.c
|
||||||
|
index 0edc3b609..d31618a56 100644
|
||||||
|
--- a/libmisc/chowndir.c
|
||||||
|
+++ b/libmisc/chowndir.c
|
||||||
|
@@ -17,45 +17,28 @@
|
||||||
|
#include "defines.h"
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
-/*
|
||||||
|
- * chown_tree - change ownership of files in a directory tree
|
||||||
|
- *
|
||||||
|
- * chown_dir() walks a directory tree and changes the ownership
|
||||||
|
- * of all files owned by the provided user ID.
|
||||||
|
- *
|
||||||
|
- * Only files owned (resp. group-owned) by old_uid (resp. by old_gid)
|
||||||
|
- * will have their ownership (resp. group-ownership) modified, unless
|
||||||
|
- * old_uid (resp. old_gid) is set to -1.
|
||||||
|
- *
|
||||||
|
- * new_uid and new_gid can be set to -1 to indicate that no owner or
|
||||||
|
- * group-owner shall be changed.
|
||||||
|
- */
|
||||||
|
-int chown_tree (const char *root,
|
||||||
|
+#include <unistd.h>
|
||||||
|
+
|
||||||
|
+static int chown_tree_at (int at_fd,
|
||||||
|
+ const char *path,
|
||||||
|
uid_t old_uid,
|
||||||
|
uid_t new_uid,
|
||||||
|
gid_t old_gid,
|
||||||
|
gid_t new_gid)
|
||||||
|
{
|
||||||
|
- char *new_name;
|
||||||
|
- size_t new_name_len;
|
||||||
|
- int rc = 0;
|
||||||
|
- struct DIRECT *ent;
|
||||||
|
- struct stat sb;
|
||||||
|
DIR *dir;
|
||||||
|
+ const struct DIRECT *ent;
|
||||||
|
+ struct stat dir_sb;
|
||||||
|
+ int dir_fd, rc = 0;
|
||||||
|
|
||||||
|
- new_name = malloc (1024);
|
||||||
|
- if (NULL == new_name) {
|
||||||
|
+ dir_fd = openat (at_fd, path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
|
||||||
|
+ if (dir_fd < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
- new_name_len = 1024;
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * Make certain the directory exists. This routine is called
|
||||||
|
- * directly by the invoker, or recursively.
|
||||||
|
- */
|
||||||
|
-
|
||||||
|
- if (access (root, F_OK) != 0) {
|
||||||
|
- free (new_name);
|
||||||
|
+ dir = fdopendir (dir_fd);
|
||||||
|
+ if (!dir) {
|
||||||
|
+ (void) close (dir_fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -65,68 +48,34 @@ int chown_tree (const char *root,
|
||||||
|
* recursively. If not, it is checked to see if an ownership
|
||||||
|
* shall be changed.
|
||||||
|
*/
|
||||||
|
-
|
||||||
|
- dir = opendir (root);
|
||||||
|
- if (NULL == dir) {
|
||||||
|
- free (new_name);
|
||||||
|
- return -1;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
while ((ent = readdir (dir))) {
|
||||||
|
- size_t ent_name_len;
|
||||||
|
uid_t tmpuid = (uid_t) -1;
|
||||||
|
gid_t tmpgid = (gid_t) -1;
|
||||||
|
+ struct stat ent_sb;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip the "." and ".." entries
|
||||||
|
*/
|
||||||
|
-
|
||||||
|
if ( (strcmp (ent->d_name, ".") == 0)
|
||||||
|
|| (strcmp (ent->d_name, "..") == 0)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * Make the filename for both the source and the
|
||||||
|
- * destination files.
|
||||||
|
- */
|
||||||
|
-
|
||||||
|
- ent_name_len = strlen (root) + strlen (ent->d_name) + 2;
|
||||||
|
- if (ent_name_len > new_name_len) {
|
||||||
|
- /*@only@*/char *tmp = realloc (new_name, ent_name_len);
|
||||||
|
- if (NULL == tmp) {
|
||||||
|
- rc = -1;
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
- new_name = tmp;
|
||||||
|
- new_name_len = ent_name_len;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- (void) snprintf (new_name, new_name_len, "%s/%s", root, ent->d_name);
|
||||||
|
-
|
||||||
|
- /* Don't follow symbolic links! */
|
||||||
|
- if (LSTAT (new_name, &sb) == -1) {
|
||||||
|
- continue;
|
||||||
|
+ rc = fstatat (dirfd(dir), ent->d_name, &ent_sb, AT_SYMLINK_NOFOLLOW);
|
||||||
|
+ if (rc < 0) {
|
||||||
|
+ break;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (S_ISDIR (sb.st_mode) && !S_ISLNK (sb.st_mode)) {
|
||||||
|
-
|
||||||
|
+ if (S_ISDIR (ent_sb.st_mode)) {
|
||||||
|
/*
|
||||||
|
* Do the entire subdirectory.
|
||||||
|
*/
|
||||||
|
-
|
||||||
|
- rc = chown_tree (new_name, old_uid, new_uid,
|
||||||
|
- old_gid, new_gid);
|
||||||
|
+ rc = chown_tree_at (dirfd(dir), ent->d_name, old_uid, new_uid, old_gid, new_gid);
|
||||||
|
if (0 != rc) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-#ifndef HAVE_LCHOWN
|
||||||
|
- /* don't use chown (follows symbolic links!) */
|
||||||
|
- if (S_ISLNK (sb.st_mode)) {
|
||||||
|
- continue;
|
||||||
|
- }
|
||||||
|
-#endif
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* By default, the IDs are not changed (-1).
|
||||||
|
*
|
||||||
|
@@ -136,43 +85,62 @@ int chown_tree (const char *root,
|
||||||
|
* If the file is not group-owned by the group, the
|
||||||
|
* group-owner is not changed.
|
||||||
|
*/
|
||||||
|
- if (((uid_t) -1 == old_uid) || (sb.st_uid == old_uid)) {
|
||||||
|
+ if (((uid_t) -1 == old_uid) || (ent_sb.st_uid == old_uid)) {
|
||||||
|
tmpuid = new_uid;
|
||||||
|
}
|
||||||
|
- if (((gid_t) -1 == old_gid) || (sb.st_gid == old_gid)) {
|
||||||
|
+ if (((gid_t) -1 == old_gid) || (ent_sb.st_gid == old_gid)) {
|
||||||
|
tmpgid = new_gid;
|
||||||
|
}
|
||||||
|
if (((uid_t) -1 != tmpuid) || ((gid_t) -1 != tmpgid)) {
|
||||||
|
- rc = LCHOWN (new_name, tmpuid, tmpgid);
|
||||||
|
+ rc = fchownat (dirfd(dir), ent->d_name, tmpuid, tmpgid, AT_SYMLINK_NOFOLLOW);
|
||||||
|
if (0 != rc) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- free (new_name);
|
||||||
|
- (void) closedir (dir);
|
||||||
|
-
|
||||||
|
/*
|
||||||
|
* Now do the root of the tree
|
||||||
|
*/
|
||||||
|
-
|
||||||
|
- if ((0 == rc) && (stat (root, &sb) == 0)) {
|
||||||
|
+ if ((0 == rc) && (fstat (dirfd(dir), &dir_sb) == 0)) {
|
||||||
|
uid_t tmpuid = (uid_t) -1;
|
||||||
|
gid_t tmpgid = (gid_t) -1;
|
||||||
|
- if (((uid_t) -1 == old_uid) || (sb.st_uid == old_uid)) {
|
||||||
|
+ if (((uid_t) -1 == old_uid) || (dir_sb.st_uid == old_uid)) {
|
||||||
|
tmpuid = new_uid;
|
||||||
|
}
|
||||||
|
- if (((gid_t) -1 == old_gid) || (sb.st_gid == old_gid)) {
|
||||||
|
+ if (((gid_t) -1 == old_gid) || (dir_sb.st_gid == old_gid)) {
|
||||||
|
tmpgid = new_gid;
|
||||||
|
}
|
||||||
|
if (((uid_t) -1 != tmpuid) || ((gid_t) -1 != tmpgid)) {
|
||||||
|
- rc = LCHOWN (root, tmpuid, tmpgid);
|
||||||
|
+ rc = fchown (dirfd(dir), tmpuid, tmpgid);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void) closedir (dir);
|
||||||
|
+
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * chown_tree - change ownership of files in a directory tree
|
||||||
|
+ *
|
||||||
|
+ * chown_dir() walks a directory tree and changes the ownership
|
||||||
|
+ * of all files owned by the provided user ID.
|
||||||
|
+ *
|
||||||
|
+ * Only files owned (resp. group-owned) by old_uid (resp. by old_gid)
|
||||||
|
+ * will have their ownership (resp. group-ownership) modified, unless
|
||||||
|
+ * old_uid (resp. old_gid) is set to -1.
|
||||||
|
+ *
|
||||||
|
+ * new_uid and new_gid can be set to -1 to indicate that no owner or
|
||||||
|
+ * group-owner shall be changed.
|
||||||
|
+ */
|
||||||
|
+int chown_tree (const char *root,
|
||||||
|
+ uid_t old_uid,
|
||||||
|
+ uid_t new_uid,
|
||||||
|
+ gid_t old_gid,
|
||||||
|
+ gid_t new_gid)
|
||||||
|
+{
|
||||||
|
+ return chown_tree_at (AT_FDCWD, root, old_uid, new_uid, old_gid, new_gid);
|
||||||
|
+}
|
||||||
657
backport-Avoid-races-in-copy_tree.patch
Normal file
657
backport-Avoid-races-in-copy_tree.patch
Normal file
@ -0,0 +1,657 @@
|
|||||||
|
From faeab50e710131816b261de66141524898c2c487 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
|
||||||
|
Date: Fri, 5 Aug 2022 17:57:32 +0200
|
||||||
|
Subject: [PATCH] Avoid races in copy_tree()
|
||||||
|
|
||||||
|
Use *at() functions to pin the directory operating in to avoid being
|
||||||
|
redirected by unprivileged users replacing parts of paths by symlinks to
|
||||||
|
privileged files.
|
||||||
|
|
||||||
|
Introduce a path_info struct with the full path and dirfd and name
|
||||||
|
information for *at() functions, since the full path is needed for link
|
||||||
|
resolution, SELinux label lookup and ACL attributes.
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/faeab50e710131816b261de66141524898c2c487
|
||||||
|
|
||||||
|
---
|
||||||
|
libmisc/copydir.c | 330 ++++++++++++++++++++++++++++++----------------
|
||||||
|
1 file changed, 218 insertions(+), 112 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmisc/copydir.c b/libmisc/copydir.c
|
||||||
|
index e753d7cf0..5605f6fe0 100644
|
||||||
|
--- a/libmisc/copydir.c
|
||||||
|
+++ b/libmisc/copydir.c
|
||||||
|
@@ -47,40 +47,43 @@ struct link_name {
|
||||||
|
};
|
||||||
|
static /*@exposed@*/struct link_name *links;
|
||||||
|
|
||||||
|
-static int copy_entry (const char *src, const char *dst,
|
||||||
|
+struct path_info {
|
||||||
|
+ const char *full_path;
|
||||||
|
+ int dirfd;
|
||||||
|
+ const char *name;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int copy_entry (const struct path_info *src, const struct path_info *dst,
|
||||||
|
bool reset_selinux,
|
||||||
|
uid_t old_uid, uid_t new_uid,
|
||||||
|
gid_t old_gid, gid_t new_gid);
|
||||||
|
-static int copy_dir (const char *src, const char *dst,
|
||||||
|
+static int copy_dir (const struct path_info *src, const struct path_info *dst,
|
||||||
|
bool reset_selinux,
|
||||||
|
- const struct stat *statp, const struct timeval mt[],
|
||||||
|
+ const struct stat *statp, const struct timespec mt[],
|
||||||
|
uid_t old_uid, uid_t new_uid,
|
||||||
|
gid_t old_gid, gid_t new_gid);
|
||||||
|
static /*@null@*/char *readlink_malloc (const char *filename);
|
||||||
|
-static int copy_symlink (const char *src, const char *dst,
|
||||||
|
+static int copy_symlink (const struct path_info *src, const struct path_info *dst,
|
||||||
|
unused bool reset_selinux,
|
||||||
|
- const struct stat *statp, const struct timeval mt[],
|
||||||
|
+ const struct stat *statp, const struct timespec mt[],
|
||||||
|
uid_t old_uid, uid_t new_uid,
|
||||||
|
gid_t old_gid, gid_t new_gid);
|
||||||
|
-static int copy_hardlink (const char *dst,
|
||||||
|
+static int copy_hardlink (const struct path_info *dst,
|
||||||
|
unused bool reset_selinux,
|
||||||
|
struct link_name *lp);
|
||||||
|
-static int copy_special (const char *src, const char *dst,
|
||||||
|
+static int copy_special (const struct path_info *src, const struct path_info *dst,
|
||||||
|
bool reset_selinux,
|
||||||
|
- const struct stat *statp, const struct timeval mt[],
|
||||||
|
+ const struct stat *statp, const struct timespec mt[],
|
||||||
|
uid_t old_uid, uid_t new_uid,
|
||||||
|
gid_t old_gid, gid_t new_gid);
|
||||||
|
-static int copy_file (const char *src, const char *dst,
|
||||||
|
+static int copy_file (const struct path_info *src, const struct path_info *dst,
|
||||||
|
bool reset_selinux,
|
||||||
|
- const struct stat *statp, const struct timeval mt[],
|
||||||
|
+ const struct stat *statp, const struct timespec mt[],
|
||||||
|
uid_t old_uid, uid_t new_uid,
|
||||||
|
gid_t old_gid, gid_t new_gid);
|
||||||
|
-static int chown_if_needed (const char *dst, const struct stat *statp,
|
||||||
|
+static int chownat_if_needed (const struct path_info *dst, const struct stat *statp,
|
||||||
|
uid_t old_uid, uid_t new_uid,
|
||||||
|
gid_t old_gid, gid_t new_gid);
|
||||||
|
-static int lchown_if_needed (const char *dst, const struct stat *statp,
|
||||||
|
- uid_t old_uid, uid_t new_uid,
|
||||||
|
- gid_t old_gid, gid_t new_gid);
|
||||||
|
static int fchown_if_needed (int fdst, const struct stat *statp,
|
||||||
|
uid_t old_uid, uid_t new_uid,
|
||||||
|
gid_t old_gid, gid_t new_gid);
|
||||||
|
@@ -116,6 +119,57 @@ static struct error_context ctx = {
|
||||||
|
};
|
||||||
|
#endif /* WITH_ACL || WITH_ATTR */
|
||||||
|
|
||||||
|
+#ifdef WITH_ACL
|
||||||
|
+static int perm_copy_path(const struct path_info *src,
|
||||||
|
+ const struct path_info *dst,
|
||||||
|
+ struct error_context *errctx)
|
||||||
|
+{
|
||||||
|
+ int src_fd, dst_fd, ret;
|
||||||
|
+
|
||||||
|
+ src_fd = openat(src->dirfd, src->name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
|
||||||
|
+ if (src_fd < 0) {
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dst_fd = openat(dst->dirfd, dst->name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
|
||||||
|
+ if (dst_fd < 0) {
|
||||||
|
+ (void) close (src_fd);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = perm_copy_fd(src->full_path, src_fd, dst->full_path, dst_fd, errctx);
|
||||||
|
+ (void) close (src_fd);
|
||||||
|
+ (void) close (dst_fd);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+#endif /* WITH_ACL */
|
||||||
|
+
|
||||||
|
+#ifdef WITH_ATTR
|
||||||
|
+static int attr_copy_path(const struct path_info *src,
|
||||||
|
+ const struct path_info *dst,
|
||||||
|
+ int (*callback) (const char *, struct error_context *),
|
||||||
|
+ struct error_context *errctx)
|
||||||
|
+{
|
||||||
|
+ int src_fd, dst_fd, ret;
|
||||||
|
+
|
||||||
|
+ src_fd = openat(src->dirfd, src->name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
|
||||||
|
+ if (src_fd < 0) {
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dst_fd = openat(dst->dirfd, dst->name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
|
||||||
|
+ if (dst_fd < 0) {
|
||||||
|
+ (void) close (src_fd);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = attr_copy_fd(src->full_path, src_fd, dst->full_path, dst_fd, callback, errctx);
|
||||||
|
+ (void) close (src_fd);
|
||||||
|
+ (void) close (dst_fd);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+#endif /* WITH_ATTR */
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* remove_link - delete a link from the linked list
|
||||||
|
*/
|
||||||
|
@@ -188,51 +242,36 @@ static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, c
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
-/*
|
||||||
|
- * copy_tree - copy files in a directory tree
|
||||||
|
- *
|
||||||
|
- * copy_tree() walks a directory tree and copies ordinary files
|
||||||
|
- * as it goes.
|
||||||
|
- *
|
||||||
|
- * When reset_selinux is enabled, extended attributes (and thus
|
||||||
|
- * SELinux attributes) are not copied.
|
||||||
|
- *
|
||||||
|
- * old_uid and new_uid are used to set the ownership of the copied
|
||||||
|
- * files. Unless old_uid is set to -1, only the files owned by
|
||||||
|
- * old_uid have their ownership changed to new_uid. In addition, if
|
||||||
|
- * new_uid is set to -1, no ownership will be changed.
|
||||||
|
- *
|
||||||
|
- * The same logic applies for the group-ownership and
|
||||||
|
- * old_gid/new_gid.
|
||||||
|
- */
|
||||||
|
-int copy_tree (const char *src_root, const char *dst_root,
|
||||||
|
+static int copy_tree_impl (const struct path_info *src, const struct path_info *dst,
|
||||||
|
bool copy_root, bool reset_selinux,
|
||||||
|
uid_t old_uid, uid_t new_uid,
|
||||||
|
gid_t old_gid, gid_t new_gid)
|
||||||
|
{
|
||||||
|
- int err = 0;
|
||||||
|
+ int dst_fd, src_fd, err = 0;
|
||||||
|
bool set_orig = false;
|
||||||
|
- struct DIRECT *ent;
|
||||||
|
+ const struct DIRECT *ent;
|
||||||
|
DIR *dir;
|
||||||
|
|
||||||
|
if (copy_root) {
|
||||||
|
struct stat sb;
|
||||||
|
- if (access (dst_root, F_OK) == 0) {
|
||||||
|
+
|
||||||
|
+ if ( fstatat (dst->dirfd, dst->name, &sb, 0) == 0
|
||||||
|
+ || errno != ENOENT) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (lstat (src_root, &sb) == -1) {
|
||||||
|
+ if (fstatat (src->dirfd, src->name, &sb, AT_SYMLINK_NOFOLLOW) == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!S_ISDIR (sb.st_mode)) {
|
||||||
|
fprintf (shadow_logfd,
|
||||||
|
"%s: %s is not a directory",
|
||||||
|
- Prog, src_root);
|
||||||
|
+ Prog, src->full_path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return copy_entry (src_root, dst_root, reset_selinux,
|
||||||
|
+ return copy_entry (src, dst, reset_selinux,
|
||||||
|
old_uid, new_uid, old_gid, new_gid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -242,8 +281,14 @@ int copy_tree (const char *src_root, const char *dst_root,
|
||||||
|
* target is created. It assumes the target directory exists.
|
||||||
|
*/
|
||||||
|
|
||||||
|
- if ( (access (src_root, F_OK) != 0)
|
||||||
|
- || (access (dst_root, F_OK) != 0)) {
|
||||||
|
+ src_fd = openat (src->dirfd, src->name, O_DIRECTORY | O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
|
||||||
|
+ if (src_fd < 0) {
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dst_fd = openat (dst->dirfd, dst->name, O_DIRECTORY | O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
|
||||||
|
+ if (dst_fd < 0) {
|
||||||
|
+ (void) close (src_fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -254,14 +299,16 @@ int copy_tree (const char *src_root, const char *dst_root,
|
||||||
|
* regular files (and directories ...) are copied, and no file
|
||||||
|
* is made set-ID.
|
||||||
|
*/
|
||||||
|
- dir = opendir (src_root);
|
||||||
|
+ dir = fdopendir (src_fd);
|
||||||
|
if (NULL == dir) {
|
||||||
|
+ (void) close (src_fd);
|
||||||
|
+ (void) close (dst_fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src_orig == NULL) {
|
||||||
|
- src_orig = src_root;
|
||||||
|
- dst_orig = dst_root;
|
||||||
|
+ src_orig = src->full_path;
|
||||||
|
+ dst_orig = dst->full_path;
|
||||||
|
set_orig = true;
|
||||||
|
}
|
||||||
|
while ((0 == err) && (ent = readdir (dir)) != NULL) {
|
||||||
|
@@ -274,8 +321,8 @@ int copy_tree (const char *src_root, const char *dst_root,
|
||||||
|
char *dst_name;
|
||||||
|
size_t src_len = strlen (ent->d_name) + 2;
|
||||||
|
size_t dst_len = strlen (ent->d_name) + 2;
|
||||||
|
- src_len += strlen (src_root);
|
||||||
|
- dst_len += strlen (dst_root);
|
||||||
|
+ src_len += strlen (src->full_path);
|
||||||
|
+ dst_len += strlen (dst->full_path);
|
||||||
|
|
||||||
|
src_name = (char *) malloc (src_len);
|
||||||
|
dst_name = (char *) malloc (dst_len);
|
||||||
|
@@ -287,12 +334,22 @@ int copy_tree (const char *src_root, const char *dst_root,
|
||||||
|
* Build the filename for both the source and
|
||||||
|
* the destination files.
|
||||||
|
*/
|
||||||
|
+ struct path_info src_entry, dst_entry;
|
||||||
|
+
|
||||||
|
(void) snprintf (src_name, src_len, "%s/%s",
|
||||||
|
- src_root, ent->d_name);
|
||||||
|
+ src->full_path, ent->d_name);
|
||||||
|
(void) snprintf (dst_name, dst_len, "%s/%s",
|
||||||
|
- dst_root, ent->d_name);
|
||||||
|
+ dst->full_path, ent->d_name);
|
||||||
|
+
|
||||||
|
+ src_entry.full_path = src_name;
|
||||||
|
+ src_entry.dirfd = dirfd(dir);
|
||||||
|
+ src_entry.name = ent->d_name;
|
||||||
|
|
||||||
|
- err = copy_entry (src_name, dst_name,
|
||||||
|
+ dst_entry.full_path = dst_name;
|
||||||
|
+ dst_entry.dirfd = dst_fd;
|
||||||
|
+ dst_entry.name = ent->d_name;
|
||||||
|
+
|
||||||
|
+ err = copy_entry (&src_entry, &dst_entry,
|
||||||
|
reset_selinux,
|
||||||
|
old_uid, new_uid,
|
||||||
|
old_gid, new_gid);
|
||||||
|
@@ -306,6 +363,7 @@ int copy_tree (const char *src_root, const char *dst_root,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(void) closedir (dir);
|
||||||
|
+ (void) close (dst_fd);
|
||||||
|
|
||||||
|
if (set_orig) {
|
||||||
|
src_orig = NULL;
|
||||||
|
@@ -352,7 +410,7 @@ int copy_tree (const char *src_root, const char *dst_root,
|
||||||
|
* old_gid) will be modified, unless old_uid (resp. old_gid) is set
|
||||||
|
* to -1.
|
||||||
|
*/
|
||||||
|
-static int copy_entry (const char *src, const char *dst,
|
||||||
|
+static int copy_entry (const struct path_info *src, const struct path_info *dst,
|
||||||
|
bool reset_selinux,
|
||||||
|
uid_t old_uid, uid_t new_uid,
|
||||||
|
gid_t old_gid, gid_t new_gid)
|
||||||
|
@@ -360,32 +418,32 @@ static int copy_entry (const char *src, const char *dst,
|
||||||
|
int err = 0;
|
||||||
|
struct stat sb;
|
||||||
|
struct link_name *lp;
|
||||||
|
- struct timeval mt[2];
|
||||||
|
+ struct timespec mt[2];
|
||||||
|
|
||||||
|
- if (lstat (src, &sb) == -1) {
|
||||||
|
+ if (fstatat(src->dirfd, src->name, &sb, AT_SYMLINK_NOFOLLOW) == -1) {
|
||||||
|
/* If we cannot stat the file, do not care. */
|
||||||
|
} else {
|
||||||
|
#ifdef HAVE_STRUCT_STAT_ST_ATIM
|
||||||
|
mt[0].tv_sec = sb.st_atim.tv_sec;
|
||||||
|
- mt[0].tv_usec = sb.st_atim.tv_nsec / 1000;
|
||||||
|
+ mt[0].tv_nsec = sb.st_atim.tv_nsec;
|
||||||
|
#else /* !HAVE_STRUCT_STAT_ST_ATIM */
|
||||||
|
mt[0].tv_sec = sb.st_atime;
|
||||||
|
# ifdef HAVE_STRUCT_STAT_ST_ATIMENSEC
|
||||||
|
- mt[0].tv_usec = sb.st_atimensec / 1000;
|
||||||
|
+ mt[0].tv_nsec = sb.st_atimensec;
|
||||||
|
# else /* !HAVE_STRUCT_STAT_ST_ATIMENSEC */
|
||||||
|
- mt[0].tv_usec = 0;
|
||||||
|
+ mt[0].tv_nsec = 0;
|
||||||
|
# endif /* !HAVE_STRUCT_STAT_ST_ATIMENSEC */
|
||||||
|
#endif /* !HAVE_STRUCT_STAT_ST_ATIM */
|
||||||
|
|
||||||
|
#ifdef HAVE_STRUCT_STAT_ST_MTIM
|
||||||
|
mt[1].tv_sec = sb.st_mtim.tv_sec;
|
||||||
|
- mt[1].tv_usec = sb.st_mtim.tv_nsec / 1000;
|
||||||
|
+ mt[1].tv_nsec = sb.st_mtim.tv_nsec;
|
||||||
|
#else /* !HAVE_STRUCT_STAT_ST_MTIM */
|
||||||
|
mt[1].tv_sec = sb.st_mtime;
|
||||||
|
# ifdef HAVE_STRUCT_STAT_ST_MTIMENSEC
|
||||||
|
- mt[1].tv_usec = sb.st_mtimensec / 1000;
|
||||||
|
+ mt[1].tv_nsec = sb.st_mtimensec;
|
||||||
|
# else /* !HAVE_STRUCT_STAT_ST_MTIMENSEC */
|
||||||
|
- mt[1].tv_usec = 0;
|
||||||
|
+ mt[1].tv_nsec = 0;
|
||||||
|
# endif /* !HAVE_STRUCT_STAT_ST_MTIMENSEC */
|
||||||
|
#endif /* !HAVE_STRUCT_STAT_ST_MTIM */
|
||||||
|
|
||||||
|
@@ -407,7 +465,7 @@ static int copy_entry (const char *src, const char *dst,
|
||||||
|
* See if this is a previously copied link
|
||||||
|
*/
|
||||||
|
|
||||||
|
- else if ((lp = check_link (src, &sb)) != NULL) {
|
||||||
|
+ else if ((lp = check_link (src->full_path, &sb)) != NULL) {
|
||||||
|
err = copy_hardlink (dst, reset_selinux, lp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -446,9 +504,9 @@ static int copy_entry (const char *src, const char *dst,
|
||||||
|
*
|
||||||
|
* Return 0 on success, -1 on error.
|
||||||
|
*/
|
||||||
|
-static int copy_dir (const char *src, const char *dst,
|
||||||
|
+static int copy_dir (const struct path_info *src, const struct path_info *dst,
|
||||||
|
bool reset_selinux,
|
||||||
|
- const struct stat *statp, const struct timeval mt[],
|
||||||
|
+ const struct stat *statp, const struct timespec mt[],
|
||||||
|
uid_t old_uid, uid_t new_uid,
|
||||||
|
gid_t old_gid, gid_t new_gid)
|
||||||
|
{
|
||||||
|
@@ -460,15 +518,15 @@ static int copy_dir (const char *src, const char *dst,
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef WITH_SELINUX
|
||||||
|
- if (set_selinux_file_context (dst, S_IFDIR) != 0) {
|
||||||
|
+ if (set_selinux_file_context (dst->full_path, S_IFDIR) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif /* WITH_SELINUX */
|
||||||
|
- if ( (mkdir (dst, statp->st_mode) != 0)
|
||||||
|
- || (chown_if_needed (dst, statp,
|
||||||
|
+ if ( (mkdirat (dst->dirfd, dst->name, statp->st_mode) != 0)
|
||||||
|
+ || (chownat_if_needed (dst, statp,
|
||||||
|
old_uid, new_uid, old_gid, new_gid) != 0)
|
||||||
|
#ifdef WITH_ACL
|
||||||
|
- || ( (perm_copy_file (src, dst, &ctx) != 0)
|
||||||
|
+ || ( (perm_copy_path (src, dst, &ctx) != 0)
|
||||||
|
&& (errno != 0))
|
||||||
|
#else /* !WITH_ACL */
|
||||||
|
|| (chmod (dst, statp->st_mode) != 0)
|
||||||
|
@@ -482,12 +540,12 @@ static int copy_dir (const char *src, const char *dst,
|
||||||
|
* additional logic so that no unexpected permissions result.
|
||||||
|
*/
|
||||||
|
|| ( !reset_selinux
|
||||||
|
- && (attr_copy_file (src, dst, NULL, &ctx) != 0)
|
||||||
|
+ && (attr_copy_path (src, dst, NULL, &ctx) != 0)
|
||||||
|
&& (errno != 0))
|
||||||
|
#endif /* WITH_ATTR */
|
||||||
|
- || (copy_tree (src, dst, false, reset_selinux,
|
||||||
|
+ || (copy_tree_impl (src, dst, false, reset_selinux,
|
||||||
|
old_uid, new_uid, old_gid, new_gid) != 0)
|
||||||
|
- || (utimes (dst, mt) != 0)) {
|
||||||
|
+ || (utimensat (dst->dirfd, dst->name, mt, AT_SYMLINK_NOFOLLOW) != 0)) {
|
||||||
|
err = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -540,9 +598,9 @@ static /*@null@*/char *readlink_malloc (const char *filename)
|
||||||
|
*
|
||||||
|
* Return 0 on success, -1 on error.
|
||||||
|
*/
|
||||||
|
-static int copy_symlink (const char *src, const char *dst,
|
||||||
|
+static int copy_symlink (const struct path_info *src, const struct path_info *dst,
|
||||||
|
unused bool reset_selinux,
|
||||||
|
- const struct stat *statp, const struct timeval mt[],
|
||||||
|
+ const struct stat *statp, const struct timespec mt[],
|
||||||
|
uid_t old_uid, uid_t new_uid,
|
||||||
|
gid_t old_gid, gid_t new_gid)
|
||||||
|
{
|
||||||
|
@@ -560,7 +618,7 @@ static int copy_symlink (const char *src, const char *dst,
|
||||||
|
* destination directory name.
|
||||||
|
*/
|
||||||
|
|
||||||
|
- oldlink = readlink_malloc (src);
|
||||||
|
+ oldlink = readlink_malloc (src->full_path);
|
||||||
|
if (NULL == oldlink) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
@@ -580,13 +638,13 @@ static int copy_symlink (const char *src, const char *dst,
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_SELINUX
|
||||||
|
- if (set_selinux_file_context (dst, S_IFLNK) != 0) {
|
||||||
|
+ if (set_selinux_file_context (dst->full_path, S_IFLNK) != 0) {
|
||||||
|
free (oldlink);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif /* WITH_SELINUX */
|
||||||
|
- if ( (symlink (oldlink, dst) != 0)
|
||||||
|
- || (lchown_if_needed (dst, statp,
|
||||||
|
+ if ( (symlinkat (oldlink, dst->dirfd, dst->name) != 0)
|
||||||
|
+ || (chownat_if_needed (dst, statp,
|
||||||
|
old_uid, new_uid, old_gid, new_gid) != 0)) {
|
||||||
|
/* FIXME: there are no modes on symlinks, right?
|
||||||
|
* ACL could be copied, but this would be much more
|
||||||
|
@@ -600,14 +658,9 @@ static int copy_symlink (const char *src, const char *dst,
|
||||||
|
}
|
||||||
|
free (oldlink);
|
||||||
|
|
||||||
|
-#ifdef HAVE_LUTIMES
|
||||||
|
- /* 2007-10-18: We don't care about
|
||||||
|
- * exit status of lutimes because
|
||||||
|
- * it returns ENOSYS on many system
|
||||||
|
- * - not implemented
|
||||||
|
- */
|
||||||
|
- (void) lutimes (dst, mt);
|
||||||
|
-#endif /* HAVE_LUTIMES */
|
||||||
|
+ if (utimensat (dst->dirfd, dst->name, mt, AT_SYMLINK_NOFOLLOW) != 0) {
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -619,13 +672,13 @@ static int copy_symlink (const char *src, const char *dst,
|
||||||
|
*
|
||||||
|
* Return 0 on success, -1 on error.
|
||||||
|
*/
|
||||||
|
-static int copy_hardlink (const char *dst,
|
||||||
|
+static int copy_hardlink (const struct path_info *dst,
|
||||||
|
unused bool reset_selinux,
|
||||||
|
struct link_name *lp)
|
||||||
|
{
|
||||||
|
/* FIXME: selinux, ACL, Extended Attributes needed? */
|
||||||
|
|
||||||
|
- if (link (lp->ln_name, dst) != 0) {
|
||||||
|
+ if (linkat (AT_FDCWD, lp->ln_name, dst->dirfd, dst->name, 0) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -649,28 +702,28 @@ static int copy_hardlink (const char *dst,
|
||||||
|
*
|
||||||
|
* Return 0 on success, -1 on error.
|
||||||
|
*/
|
||||||
|
-static int copy_special (const char *src, const char *dst,
|
||||||
|
+static int copy_special (const struct path_info *src, const struct path_info *dst,
|
||||||
|
bool reset_selinux,
|
||||||
|
- const struct stat *statp, const struct timeval mt[],
|
||||||
|
+ const struct stat *statp, const struct timespec mt[],
|
||||||
|
uid_t old_uid, uid_t new_uid,
|
||||||
|
gid_t old_gid, gid_t new_gid)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
#ifdef WITH_SELINUX
|
||||||
|
- if (set_selinux_file_context (dst, statp->st_mode & S_IFMT) != 0) {
|
||||||
|
+ if (set_selinux_file_context (dst->full_path, statp->st_mode & S_IFMT) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif /* WITH_SELINUX */
|
||||||
|
|
||||||
|
- if ( (mknod (dst, statp->st_mode & ~07777U, statp->st_rdev) != 0)
|
||||||
|
- || (chown_if_needed (dst, statp,
|
||||||
|
+ if ( (mknodat (dst->dirfd, dst->name, statp->st_mode & ~07777U, statp->st_rdev) != 0)
|
||||||
|
+ || (chownat_if_needed (dst, statp,
|
||||||
|
old_uid, new_uid, old_gid, new_gid) != 0)
|
||||||
|
#ifdef WITH_ACL
|
||||||
|
- || ( (perm_copy_file (src, dst, &ctx) != 0)
|
||||||
|
+ || ( (perm_copy_path (src, dst, &ctx) != 0)
|
||||||
|
&& (errno != 0))
|
||||||
|
#else /* !WITH_ACL */
|
||||||
|
- || (chmod (dst, statp->st_mode & 07777) != 0)
|
||||||
|
+ || (fchmodat (dst->dirfd, dst->name, statp->st_mode & 07777, AT_SYMLINK_NOFOLLOW) != 0)
|
||||||
|
#endif /* !WITH_ACL */
|
||||||
|
#ifdef WITH_ATTR
|
||||||
|
/*
|
||||||
|
@@ -681,10 +734,10 @@ static int copy_special (const char *src, const char *dst,
|
||||||
|
* additional logic so that no unexpected permissions result.
|
||||||
|
*/
|
||||||
|
|| ( !reset_selinux
|
||||||
|
- && (attr_copy_file (src, dst, NULL, &ctx) != 0)
|
||||||
|
+ && (attr_copy_path (src, dst, NULL, &ctx) != 0)
|
||||||
|
&& (errno != 0))
|
||||||
|
#endif /* WITH_ATTR */
|
||||||
|
- || (utimes (dst, mt) != 0)) {
|
||||||
|
+ || (utimensat (dst->dirfd, dst->name, mt, AT_SYMLINK_NOFOLLOW) != 0)) {
|
||||||
|
err = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -737,9 +790,9 @@ static ssize_t full_write(int fd, const void *buf, size_t count) {
|
||||||
|
*
|
||||||
|
* Return 0 on success, -1 on error.
|
||||||
|
*/
|
||||||
|
-static int copy_file (const char *src, const char *dst,
|
||||||
|
+static int copy_file (const struct path_info *src, const struct path_info *dst,
|
||||||
|
bool reset_selinux,
|
||||||
|
- const struct stat *statp, const struct timeval mt[],
|
||||||
|
+ const struct stat *statp, const struct timespec mt[],
|
||||||
|
uid_t old_uid, uid_t new_uid,
|
||||||
|
gid_t old_gid, gid_t new_gid)
|
||||||
|
{
|
||||||
|
@@ -747,22 +800,22 @@ static int copy_file (const char *src, const char *dst,
|
||||||
|
int ifd;
|
||||||
|
int ofd;
|
||||||
|
|
||||||
|
- ifd = open (src, O_RDONLY|O_NOFOLLOW);
|
||||||
|
+ ifd = openat (src->dirfd, src->name, O_RDONLY|O_NOFOLLOW|O_CLOEXEC);
|
||||||
|
if (ifd < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#ifdef WITH_SELINUX
|
||||||
|
- if (set_selinux_file_context (dst, S_IFREG) != 0) {
|
||||||
|
+ if (set_selinux_file_context (dst->full_path, S_IFREG) != 0) {
|
||||||
|
(void) close (ifd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif /* WITH_SELINUX */
|
||||||
|
- ofd = open (dst, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC | O_NOFOLLOW | O_CLOEXEC, statp->st_mode & 07777);
|
||||||
|
+ ofd = openat (dst->dirfd, dst->name, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC | O_NOFOLLOW | O_CLOEXEC, statp->st_mode & 07777);
|
||||||
|
if ( (ofd < 0)
|
||||||
|
|| (fchown_if_needed (ofd, statp,
|
||||||
|
old_uid, new_uid, old_gid, new_gid) != 0)
|
||||||
|
#ifdef WITH_ACL
|
||||||
|
- || ( (perm_copy_fd (src, ifd, dst, ofd, &ctx) != 0)
|
||||||
|
+ || ( (perm_copy_fd (src->full_path, ifd, dst->full_path, ofd, &ctx) != 0)
|
||||||
|
&& (errno != 0))
|
||||||
|
#else /* !WITH_ACL */
|
||||||
|
|| (fchmod (ofd, statp->st_mode & 07777) != 0)
|
||||||
|
@@ -776,7 +829,7 @@ static int copy_file (const char *src, const char *dst,
|
||||||
|
* additional logic so that no unexpected permissions result.
|
||||||
|
*/
|
||||||
|
|| ( !reset_selinux
|
||||||
|
- && (attr_copy_fd (src, ifd, dst, ofd, NULL, &ctx) != 0)
|
||||||
|
+ && (attr_copy_fd (src->full_path, ifd, dst->full_path, ofd, NULL, &ctx) != 0)
|
||||||
|
&& (errno != 0))
|
||||||
|
#endif /* WITH_ATTR */
|
||||||
|
) {
|
||||||
|
@@ -812,23 +865,13 @@ static int copy_file (const char *src, const char *dst,
|
||||||
|
}
|
||||||
|
|
||||||
|
(void) close (ifd);
|
||||||
|
-
|
||||||
|
-#ifdef HAVE_FUTIMES
|
||||||
|
- if (futimes (ofd, mt) != 0) {
|
||||||
|
- (void) close (ofd);
|
||||||
|
- return -1;
|
||||||
|
- }
|
||||||
|
-#endif /* HAVE_FUTIMES */
|
||||||
|
-
|
||||||
|
if (close (ofd) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
-#ifndef HAVE_FUTIMES
|
||||||
|
- if (utimes(dst, mt) != 0) {
|
||||||
|
+ if (utimensat (dst->dirfd, dst->name, mt, AT_SYMLINK_NOFOLLOW) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
-#endif /* !HAVE_FUTIMES */
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
@@ -863,7 +906,70 @@ static int chown_function ## _if_needed (type_dst dst, \
|
||||||
|
return chown_function (dst, tmpuid, tmpgid); \
|
||||||
|
}
|
||||||
|
|
||||||
|
-def_chown_if_needed (chown, const char *)
|
||||||
|
-def_chown_if_needed (lchown, const char *)
|
||||||
|
def_chown_if_needed (fchown, int)
|
||||||
|
|
||||||
|
+static int chownat_if_needed (const struct path_info *dst,
|
||||||
|
+ const struct stat *statp,
|
||||||
|
+ uid_t old_uid, uid_t new_uid,
|
||||||
|
+ gid_t old_gid, gid_t new_gid)
|
||||||
|
+{
|
||||||
|
+ uid_t tmpuid = (uid_t) -1;
|
||||||
|
+ gid_t tmpgid = (gid_t) -1;
|
||||||
|
+
|
||||||
|
+ /* Use new_uid if old_uid is set to -1 or if the file was
|
||||||
|
+ * owned by the user. */
|
||||||
|
+ if (((uid_t) -1 == old_uid) || (statp->st_uid == old_uid)) {
|
||||||
|
+ tmpuid = new_uid;
|
||||||
|
+ }
|
||||||
|
+ /* Otherwise, or if new_uid was set to -1, we keep the same
|
||||||
|
+ * owner. */
|
||||||
|
+ if ((uid_t) -1 == tmpuid) {
|
||||||
|
+ tmpuid = statp->st_uid;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (((gid_t) -1 == old_gid) || (statp->st_gid == old_gid)) {
|
||||||
|
+ tmpgid = new_gid;
|
||||||
|
+ }
|
||||||
|
+ if ((gid_t) -1 == tmpgid) {
|
||||||
|
+ tmpgid = statp->st_gid;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return fchownat (dst->dirfd, dst->name, tmpuid, tmpgid, AT_SYMLINK_NOFOLLOW);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * copy_tree - copy files in a directory tree
|
||||||
|
+ *
|
||||||
|
+ * copy_tree() walks a directory tree and copies ordinary files
|
||||||
|
+ * as it goes.
|
||||||
|
+ *
|
||||||
|
+ * When reset_selinux is enabled, extended attributes (and thus
|
||||||
|
+ * SELinux attributes) are not copied.
|
||||||
|
+ *
|
||||||
|
+ * old_uid and new_uid are used to set the ownership of the copied
|
||||||
|
+ * files. Unless old_uid is set to -1, only the files owned by
|
||||||
|
+ * old_uid have their ownership changed to new_uid. In addition, if
|
||||||
|
+ * new_uid is set to -1, no ownership will be changed.
|
||||||
|
+ *
|
||||||
|
+ * The same logic applies for the group-ownership and
|
||||||
|
+ * old_gid/new_gid.
|
||||||
|
+ */
|
||||||
|
+int copy_tree (const char *src_root, const char *dst_root,
|
||||||
|
+ bool copy_root, bool reset_selinux,
|
||||||
|
+ uid_t old_uid, uid_t new_uid,
|
||||||
|
+ gid_t old_gid, gid_t new_gid)
|
||||||
|
+{
|
||||||
|
+ const struct path_info src = {
|
||||||
|
+ .full_path = src_root,
|
||||||
|
+ .dirfd = AT_FDCWD,
|
||||||
|
+ .name = src_root
|
||||||
|
+ };
|
||||||
|
+ const struct path_info dst = {
|
||||||
|
+ .full_path = dst_root,
|
||||||
|
+ .dirfd = AT_FDCWD,
|
||||||
|
+ .name = dst_root
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ return copy_tree_impl(&src, &dst, copy_root, reset_selinux,
|
||||||
|
+ old_uid, new_uid, old_gid, new_gid);
|
||||||
|
+}
|
||||||
157
backport-Avoid-races-in-remove_tree.patch
Normal file
157
backport-Avoid-races-in-remove_tree.patch
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
From f6f8bcd2a57c06983296485cc028ebdf467ebfd7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
|
||||||
|
Date: Fri, 5 Aug 2022 17:57:22 +0200
|
||||||
|
Subject: [PATCH] Avoid races in remove_tree()
|
||||||
|
|
||||||
|
Use *at() functions to pin the directory operating in to avoid being
|
||||||
|
redirected by unprivileged users replacing parts of paths by symlinks to
|
||||||
|
privileged files.
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/f6f8bcd2a57c06983296485cc028ebdf467ebfd7
|
||||||
|
|
||||||
|
---
|
||||||
|
libmisc/remove_tree.c | 87 +++++++++++++++++++------------------------
|
||||||
|
1 file changed, 39 insertions(+), 48 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmisc/remove_tree.c b/libmisc/remove_tree.c
|
||||||
|
index 04bc7fc4a..3d76b95e0 100644
|
||||||
|
--- a/libmisc/remove_tree.c
|
||||||
|
+++ b/libmisc/remove_tree.c
|
||||||
|
@@ -11,6 +11,7 @@
|
||||||
|
|
||||||
|
#ident "$Id$"
|
||||||
|
|
||||||
|
+#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
@@ -21,90 +22,80 @@
|
||||||
|
#include "prototypes.h"
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
-/*
|
||||||
|
- * remove_tree - delete a directory tree
|
||||||
|
- *
|
||||||
|
- * remove_tree() walks a directory tree and deletes all the files
|
||||||
|
- * and directories.
|
||||||
|
- * At the end, it deletes the root directory itself.
|
||||||
|
- */
|
||||||
|
-
|
||||||
|
-int remove_tree (const char *root, bool remove_root)
|
||||||
|
+static int remove_tree_at (int at_fd, const char *path, bool remove_root)
|
||||||
|
{
|
||||||
|
- char *new_name = NULL;
|
||||||
|
- int err = 0;
|
||||||
|
- struct DIRECT *ent;
|
||||||
|
- struct stat sb;
|
||||||
|
DIR *dir;
|
||||||
|
+ const struct DIRECT *ent;
|
||||||
|
+ int dir_fd, rc = 0;
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * Open the source directory and read each entry. Every file
|
||||||
|
- * entry in the directory is copied with the UID and GID set
|
||||||
|
- * to the provided values. As an added security feature only
|
||||||
|
- * regular files (and directories ...) are copied, and no file
|
||||||
|
- * is made set-ID.
|
||||||
|
- */
|
||||||
|
- dir = opendir (root);
|
||||||
|
- if (NULL == dir) {
|
||||||
|
+ dir_fd = openat (at_fd, path, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
|
||||||
|
+ if (dir_fd < 0) {
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ dir = fdopendir (dir_fd);
|
||||||
|
+ if (!dir) {
|
||||||
|
+ (void) close (dir_fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Open the source directory and delete each entry.
|
||||||
|
+ */
|
||||||
|
while ((ent = readdir (dir))) {
|
||||||
|
- size_t new_len = strlen (root) + strlen (ent->d_name) + 2;
|
||||||
|
+ struct stat ent_sb;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip the "." and ".." entries
|
||||||
|
*/
|
||||||
|
-
|
||||||
|
if (strcmp (ent->d_name, ".") == 0 ||
|
||||||
|
strcmp (ent->d_name, "..") == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * Make the filename for the current entry.
|
||||||
|
- */
|
||||||
|
-
|
||||||
|
- free (new_name);
|
||||||
|
- new_name = (char *) malloc (new_len);
|
||||||
|
- if (NULL == new_name) {
|
||||||
|
- err = -1;
|
||||||
|
+ rc = fstatat (dirfd(dir), ent->d_name, &ent_sb, AT_SYMLINK_NOFOLLOW);
|
||||||
|
+ if (rc < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
- (void) snprintf (new_name, new_len, "%s/%s", root, ent->d_name);
|
||||||
|
- if (LSTAT (new_name, &sb) == -1) {
|
||||||
|
- continue;
|
||||||
|
- }
|
||||||
|
|
||||||
|
- if (S_ISDIR (sb.st_mode)) {
|
||||||
|
+ if (S_ISDIR (ent_sb.st_mode)) {
|
||||||
|
/*
|
||||||
|
* Recursively delete this directory.
|
||||||
|
*/
|
||||||
|
- if (remove_tree (new_name, true) != 0) {
|
||||||
|
- err = -1;
|
||||||
|
+ if (remove_tree_at (dirfd(dir), ent->d_name, true) != 0) {
|
||||||
|
+ rc = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Delete the file.
|
||||||
|
*/
|
||||||
|
- if (unlink (new_name) != 0) {
|
||||||
|
- err = -1;
|
||||||
|
+ if (unlinkat (dirfd(dir), ent->d_name, 0) != 0) {
|
||||||
|
+ rc = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- if (NULL != new_name) {
|
||||||
|
- free (new_name);
|
||||||
|
- }
|
||||||
|
+
|
||||||
|
(void) closedir (dir);
|
||||||
|
|
||||||
|
- if (remove_root && (0 == err)) {
|
||||||
|
- if (rmdir (root) != 0) {
|
||||||
|
- err = -1;
|
||||||
|
+ if (remove_root && (0 == rc)) {
|
||||||
|
+ if (unlinkat (at_fd, path, AT_REMOVEDIR) != 0) {
|
||||||
|
+ rc = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- return err;
|
||||||
|
+ return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * remove_tree - delete a directory tree
|
||||||
|
+ *
|
||||||
|
+ * remove_tree() walks a directory tree and deletes all the files
|
||||||
|
+ * and directories.
|
||||||
|
+ * At the end, it deletes the root directory itself.
|
||||||
|
+ */
|
||||||
|
+int remove_tree (const char *root, bool remove_root)
|
||||||
|
+{
|
||||||
|
+ return remove_tree_at (AT_FDCWD, root, remove_root);
|
||||||
|
+}
|
||||||
34
backport-CVE-2013-4235.patch
Normal file
34
backport-CVE-2013-4235.patch
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
From b4472167c2f5057d56686d3349a9b55fc508efe6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: ed neville <ed@s5h.net>
|
||||||
|
Date: Fri, 31 Dec 2021 22:40:13 +0000
|
||||||
|
Subject: [PATCH] Adding nofollow to opens
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/b4472167c2f5057d56686d3349a9b55fc508efe6
|
||||||
|
|
||||||
|
---
|
||||||
|
libmisc/copydir.c | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmisc/copydir.c b/libmisc/copydir.c
|
||||||
|
index f2130bcac..a296d925d 100644
|
||||||
|
--- a/libmisc/copydir.c
|
||||||
|
+++ b/libmisc/copydir.c
|
||||||
|
@@ -741,7 +741,7 @@ static int copy_file (const char *src, const char *dst,
|
||||||
|
char buf[1024];
|
||||||
|
ssize_t cnt;
|
||||||
|
|
||||||
|
- ifd = open (src, O_RDONLY);
|
||||||
|
+ ifd = open (src, O_RDONLY|O_NOFOLLOW);
|
||||||
|
if (ifd < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
@@ -751,7 +751,7 @@ static int copy_file (const char *src, const char *dst,
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif /* WITH_SELINUX */
|
||||||
|
- ofd = open (dst, O_WRONLY | O_CREAT | O_TRUNC, statp->st_mode & 07777);
|
||||||
|
+ ofd = open (dst, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, statp->st_mode & 07777);
|
||||||
|
if ( (ofd < 0)
|
||||||
|
|| (fchown_if_needed (ofd, statp,
|
||||||
|
old_uid, new_uid, old_gid, new_gid) != 0)
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
From b422e3c31691412f0a5404d09f7b328477e23c48 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Skyler Ferrante <sjf5462@rit.edu>
|
||||||
|
Date: Tue, 30 May 2023 15:00:12 -0400
|
||||||
|
Subject: [PATCH] Check if crypt_method null before dereferencing
|
||||||
|
|
||||||
|
Make sure crypto_method set before sha-rounds. Only affects newusers.
|
||||||
|
---
|
||||||
|
src/newusers.c | 7 +++++++
|
||||||
|
1 file changed, 7 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/src/newusers.c b/src/newusers.c
|
||||||
|
index ae2224fc..d6b7c3c3 100644
|
||||||
|
--- a/src/newusers.c
|
||||||
|
+++ b/src/newusers.c
|
||||||
|
@@ -662,6 +662,13 @@ static void process_flags (int argc, char **argv)
|
||||||
|
case 's':
|
||||||
|
sflg = true;
|
||||||
|
bad_s = 0;
|
||||||
|
+
|
||||||
|
+ if (!crypt_method){
|
||||||
|
+ fprintf(stderr,
|
||||||
|
+ _("%s: Provide '--crypt-method'\n"),
|
||||||
|
+ Prog);
|
||||||
|
+ usage (EXIT_FAILURE);
|
||||||
|
+ }
|
||||||
|
#if defined(USE_SHA_CRYPT)
|
||||||
|
if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512")))
|
||||||
|
&& (0 == getlong(optarg, &sha_rounds)))) {
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
||||||
28
backport-Fail-if-regular-file-pre-exists-in-copy_tree.patch
Normal file
28
backport-Fail-if-regular-file-pre-exists-in-copy_tree.patch
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
From 1d281273b149f2bb992d893d8ca9ffffddc95cc8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
|
||||||
|
Date: Fri, 5 Aug 2022 17:57:26 +0200
|
||||||
|
Subject: [PATCH] Fail if regular file pre-exists in copy_tree()
|
||||||
|
|
||||||
|
Similar to the default behavior of mkdir(2), symlink(2), link(2) and
|
||||||
|
mknod(2).
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/1d281273b149f2bb992d893d8ca9ffffddc95cc8
|
||||||
|
|
||||||
|
---
|
||||||
|
libmisc/copydir.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmisc/copydir.c b/libmisc/copydir.c
|
||||||
|
index 648f562a1..90895cfb0 100644
|
||||||
|
--- a/libmisc/copydir.c
|
||||||
|
+++ b/libmisc/copydir.c
|
||||||
|
@@ -723,7 +723,7 @@ static int copy_file (const char *src, const char *dst,
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif /* WITH_SELINUX */
|
||||||
|
- ofd = open (dst, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, statp->st_mode & 07777);
|
||||||
|
+ ofd = open (dst, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC | O_NOFOLLOW | O_CLOEXEC, statp->st_mode & 07777);
|
||||||
|
if ( (ofd < 0)
|
||||||
|
|| (fchown_if_needed (ofd, statp,
|
||||||
|
old_uid, new_uid, old_gid, new_gid) != 0)
|
||||||
27
backport-Fix-parentheses-in-configure.ac.patch
Normal file
27
backport-Fix-parentheses-in-configure.ac.patch
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
From 049f9a7f6b320c728a6274299041e360381d7cd5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Andy Zaugg <andy.zaugg@gmail.com>
|
||||||
|
Date: Tue, 21 Sep 2021 21:51:10 -0700
|
||||||
|
Subject: [PATCH] Fix parentheses in configure.ac
|
||||||
|
|
||||||
|
Resolving issue https://github.com/shadow-maint/shadow/issues/419
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/049f9a7f6b320c728a6274299041e360381d7cd5
|
||||||
|
|
||||||
|
---
|
||||||
|
configure.ac | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/configure.ac b/configure.ac
|
||||||
|
index 994836bda..6cbb6bd27 100644
|
||||||
|
--- a/configure.ac
|
||||||
|
+++ b/configure.ac
|
||||||
|
@@ -345,7 +345,7 @@ if test "$with_sssd" = "yes"; then
|
||||||
|
[AC_MSG_ERROR([posix_spawn is needed for sssd support])])
|
||||||
|
fi
|
||||||
|
|
||||||
|
-AS_IF([test "$with_su" != "no"], AC_DEFINE(WITH_SU, 1, [Build with su])])
|
||||||
|
+AS_IF([test "$with_su" != "no"], AC_DEFINE(WITH_SU, 1, [Build with su]))
|
||||||
|
AM_CONDITIONAL([WITH_SU], [test "x$with_su" != "xno"])
|
||||||
|
|
||||||
|
dnl Check for some functions in libc first, only if not found check for
|
||||||
37
backport-Fix-yescrypt-support.patch
Normal file
37
backport-Fix-yescrypt-support.patch
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
From 29da702491eea314b915ea9c7a83c9af80cf5797 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bernd Kuhls <bernd@kuhls.net>
|
||||||
|
Date: Sun, 9 Jul 2023 10:55:03 +0200
|
||||||
|
Subject: [PATCH] Fix yescrypt support
|
||||||
|
|
||||||
|
Fixes build error:
|
||||||
|
newusers.c: In function 'update_passwd':
|
||||||
|
newusers.c:433:21: error: 'sflg' undeclared (first use in this function); did you mean 'rflg'?
|
||||||
|
|
||||||
|
introduced by
|
||||||
|
https://github.com/shadow-maint/shadow/commit/5cd04d03f94622c12220d4a6352824af081b8531
|
||||||
|
which forgot to define sflg for these configure options:
|
||||||
|
|
||||||
|
--without-sha-crypt --without-bcrypt --with-yescrypt
|
||||||
|
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/29da702491eea314b915ea9c7a83c9af80cf5797
|
||||||
|
Conflict: NA
|
||||||
|
---
|
||||||
|
src/newusers.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/newusers.c b/src/newusers.c
|
||||||
|
index 7cb8434b..08f79798 100644
|
||||||
|
--- a/src/newusers.c
|
||||||
|
+++ b/src/newusers.c
|
||||||
|
@@ -60,7 +60,7 @@ static bool rflg = false; /* create a system account */
|
||||||
|
#ifndef USE_PAM
|
||||||
|
static /*@null@*//*@observer@*/char *crypt_method = NULL;
|
||||||
|
#define cflg (NULL != crypt_method)
|
||||||
|
-#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_SM3_CRYPT)
|
||||||
|
+#if defined(USE_SHA_CRYPT) || defined(USE_BCRYPT) || defined(USE_SM3_CRYPT) || defined(USE_YESCRYPT)
|
||||||
|
static bool sflg = false;
|
||||||
|
#endif
|
||||||
|
#ifdef USE_SHA_CRYPT
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
||||||
34
backport-Handle-malformed-lines-in-hushlogins-file.patch
Normal file
34
backport-Handle-malformed-lines-in-hushlogins-file.patch
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
From 63a96706b1205f91c4a57de21ac56e996d270ff1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Tobias Stoeckmann <tobias@stoeckmann.org>
|
||||||
|
Date: Fri, 29 Oct 2021 19:44:46 +0200
|
||||||
|
Subject: [PATCH] Handle malformed lines in hushlogins file.
|
||||||
|
|
||||||
|
If a line in hushlogins file, e.g. /etc/hushlogins, starts with
|
||||||
|
'\0', then current code performs an out of boundary write.
|
||||||
|
If the line lacks a newline at the end, then another character is
|
||||||
|
overridden.
|
||||||
|
|
||||||
|
With strcspn both cases are solved.
|
||||||
|
|
||||||
|
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/63a96706b1205f91c4a57de21ac56e996d270ff1
|
||||||
|
|
||||||
|
---
|
||||||
|
libmisc/hushed.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmisc/hushed.c b/libmisc/hushed.c
|
||||||
|
index b71b99ce2..3c3adafca 100644
|
||||||
|
--- a/libmisc/hushed.c
|
||||||
|
+++ b/libmisc/hushed.c
|
||||||
|
@@ -90,7 +90,7 @@ bool hushed (const char *username)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (found = false; !found && (fgets (buf, (int) sizeof buf, fp) == buf);) {
|
||||||
|
- buf[strlen (buf) - 1] = '\0';
|
||||||
|
+ buf[strcspn (buf, "\n")] = '\0';
|
||||||
|
found = (strcmp (buf, pw->pw_shell) == 0) ||
|
||||||
|
(strcmp (buf, pw->pw_name) == 0);
|
||||||
|
}
|
||||||
62
backport-Improve-child-error-handling.patch
Normal file
62
backport-Improve-child-error-handling.patch
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
From 624d57c08caceed306212d24c2147f6273f3fc4b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Tobias Stoeckmann <tobias@stoeckmann.org>
|
||||||
|
Date: Sun, 14 Nov 2021 12:01:32 +0100
|
||||||
|
Subject: [PATCH] Improve child error handling
|
||||||
|
|
||||||
|
Always set SIGCHLD handler to default, even if the caller of vipw has
|
||||||
|
set SIGCHLD to ignore. If SIGCHLD is ignored no zombie processes would
|
||||||
|
be created, which in turn could mean that kill is called with an already
|
||||||
|
recycled pid.
|
||||||
|
|
||||||
|
Proof of Concept:
|
||||||
|
|
||||||
|
1. Compile nochld:
|
||||||
|
--
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
int main(void) {
|
||||||
|
char *argv[] = { "vipw", NULL };
|
||||||
|
signal(SIGCHLD, SIG_IGN);
|
||||||
|
execvp("vipw", argv);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2. Run nochld
|
||||||
|
3. Suspend child vi, which suspends vipw too:
|
||||||
|
`kill -STOP childpid`
|
||||||
|
4. Kill vi:
|
||||||
|
`kill -9 childpid`
|
||||||
|
5. You can see with ps that childpid is no zombie but disappeared
|
||||||
|
6. Bring vipw back into foreground
|
||||||
|
`fg`
|
||||||
|
|
||||||
|
The kill call sends SIGCONT to "childpid" which in turn could have been
|
||||||
|
already recycled for another process.
|
||||||
|
|
||||||
|
This is definitely not a vulnerability. It would take super user
|
||||||
|
operations, at which point an attacker would have already elevated
|
||||||
|
permissions.
|
||||||
|
|
||||||
|
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/624d57c08caceed306212d24c2147f6273f3fc4b
|
||||||
|
|
||||||
|
---
|
||||||
|
src/vipw.c | 3 +++
|
||||||
|
1 file changed, 3 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/src/vipw.c b/src/vipw.c
|
||||||
|
index 94185c3df..1a69ef285 100644
|
||||||
|
--- a/src/vipw.c
|
||||||
|
+++ b/src/vipw.c
|
||||||
|
@@ -349,6 +349,9 @@ vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void))
|
||||||
|
sigprocmask(SIG_BLOCK, &mask, &omask);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* set SIGCHLD to default for waitpid */
|
||||||
|
+ signal(SIGCHLD, SIG_DFL);
|
||||||
|
+
|
||||||
|
for (;;) {
|
||||||
|
pid = waitpid (pid, &status, WUNTRACED);
|
||||||
|
if ((pid != -1) && (WIFSTOPPED (status) != 0)) {
|
||||||
98
backport-More-robust-file-content-copy-in-copy_tree.patch
Normal file
98
backport-More-robust-file-content-copy-in-copy_tree.patch
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
From f606314f0c22fb5d13e5af17a70860d57559e808 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
|
||||||
|
Date: Fri, 5 Aug 2022 17:57:27 +0200
|
||||||
|
Subject: [PATCH] More robust file content copy in copy_tree()
|
||||||
|
|
||||||
|
Bail out on read(2) failure, continue on EINTR, support short writes and
|
||||||
|
increase chunk size.
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/f606314f0c22fb5d13e5af17a70860d57559e808
|
||||||
|
|
||||||
|
---
|
||||||
|
libmisc/copydir.c | 58 +++++++++++++++++++++++++++++++++++++++++++----
|
||||||
|
1 file changed, 54 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmisc/copydir.c b/libmisc/copydir.c
|
||||||
|
index 90895cfb0..95042187b 100644
|
||||||
|
--- a/libmisc/copydir.c
|
||||||
|
+++ b/libmisc/copydir.c
|
||||||
|
@@ -691,6 +691,42 @@ static int copy_special (const char *src, const char *dst,
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * full_write - write entire buffer
|
||||||
|
+ *
|
||||||
|
+ * Write up to count bytes from the buffer starting at buf to the
|
||||||
|
+ * file referred to by the file descriptor fd.
|
||||||
|
+ * Retry in case of a short write.
|
||||||
|
+ *
|
||||||
|
+ * Returns the number of bytes written on success, -1 on error.
|
||||||
|
+ */
|
||||||
|
+static ssize_t full_write(int fd, const void *buf, size_t count) {
|
||||||
|
+ ssize_t written = 0;
|
||||||
|
+
|
||||||
|
+ while (count > 0) {
|
||||||
|
+ ssize_t res;
|
||||||
|
+
|
||||||
|
+ res = write(fd, buf, count);
|
||||||
|
+ if (res < 0) {
|
||||||
|
+ if (errno == EINTR) {
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return res;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (res == 0) {
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ written += res;
|
||||||
|
+ buf = (const unsigned char*)buf + res;
|
||||||
|
+ count -= (size_t)res;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return written;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* copy_file - copy a file
|
||||||
|
*
|
||||||
|
@@ -710,8 +746,6 @@ static int copy_file (const char *src, const char *dst,
|
||||||
|
int err = 0;
|
||||||
|
int ifd;
|
||||||
|
int ofd;
|
||||||
|
- char buf[1024];
|
||||||
|
- ssize_t cnt;
|
||||||
|
|
||||||
|
ifd = open (src, O_RDONLY|O_NOFOLLOW);
|
||||||
|
if (ifd < 0) {
|
||||||
|
@@ -753,8 +787,24 @@ static int copy_file (const char *src, const char *dst,
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- while ((cnt = read (ifd, buf, sizeof buf)) > 0) {
|
||||||
|
- if (write (ofd, buf, (size_t)cnt) != cnt) {
|
||||||
|
+ while (true) {
|
||||||
|
+ char buf[8192];
|
||||||
|
+ ssize_t cnt;
|
||||||
|
+
|
||||||
|
+ cnt = read (ifd, buf, sizeof buf);
|
||||||
|
+ if (cnt < 0) {
|
||||||
|
+ if (errno == EINTR) {
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ (void) close (ofd);
|
||||||
|
+ (void) close (ifd);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+ if (cnt == 0) {
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (full_write (ofd, buf, (size_t)cnt) < 0) {
|
||||||
|
(void) close (ofd);
|
||||||
|
(void) close (ifd);
|
||||||
|
return -1;
|
||||||
43
backport-Only-free-sgent-if-it-was-initialized.patch
Normal file
43
backport-Only-free-sgent-if-it-was-initialized.patch
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
From 117bc66c6f95fa85ca75ecfdb8fbd3615deca0b6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Vetter <jubalh@iodoru.org>
|
||||||
|
Date: Mon, 20 Sep 2021 11:04:50 +0200
|
||||||
|
Subject: [PATCH] Only free sgent if it was initialized
|
||||||
|
|
||||||
|
`sgent` is only initialized in `get_group()` if `is_shadowgrp` is true.
|
||||||
|
So we should also only attempt to free it if this is actually the case.
|
||||||
|
|
||||||
|
Can otherwise lead to:
|
||||||
|
```
|
||||||
|
free() double free detected in tcache 2 (gpasswd)
|
||||||
|
```
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/117bc66c6f95fa85ca75ecfdb8fbd3615deca0b6
|
||||||
|
|
||||||
|
---
|
||||||
|
src/gpasswd.c | 12 +++++++-----
|
||||||
|
1 file changed, 7 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/gpasswd.c b/src/gpasswd.c
|
||||||
|
index a43d9a590..04bed83d6 100644
|
||||||
|
--- a/src/gpasswd.c
|
||||||
|
+++ b/src/gpasswd.c
|
||||||
|
@@ -1207,11 +1207,13 @@ int main (int argc, char **argv)
|
||||||
|
sssd_flush_cache (SSSD_DB_GROUP);
|
||||||
|
|
||||||
|
#ifdef SHADOWGRP
|
||||||
|
- if (sgent.sg_adm) {
|
||||||
|
- xfree(sgent.sg_adm);
|
||||||
|
- }
|
||||||
|
- if (sgent.sg_mem) {
|
||||||
|
- xfree(sgent.sg_mem);
|
||||||
|
+ if (is_shadowgrp) {
|
||||||
|
+ if (sgent.sg_adm) {
|
||||||
|
+ xfree(sgent.sg_adm);
|
||||||
|
+ }
|
||||||
|
+ if (sgent.sg_mem) {
|
||||||
|
+ xfree(sgent.sg_mem);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (grent.gr_mem) {
|
||||||
42
backport-Plug-econf-memory-leaks.patch
Normal file
42
backport-Plug-econf-memory-leaks.patch
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
From 8175b1532e4bb1951264e8a6ee5f484137e5306c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Tobias Stoeckmann <tobias@stoeckmann.org>
|
||||||
|
Date: Thu, 18 May 2023 17:25:35 +0200
|
||||||
|
Subject: [PATCH] Plug econf memory leaks
|
||||||
|
|
||||||
|
You can see the memory leaks with address sanitizer if shadow is
|
||||||
|
compiled with `--enable-vendordir=/usr/etc`.
|
||||||
|
|
||||||
|
How to reproduce:
|
||||||
|
|
||||||
|
1. Prepare a custom shell file as root
|
||||||
|
```
|
||||||
|
mkdir -p /etc/shells.d
|
||||||
|
echo /bin/myshell > /etc/shells.d/custom
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Run chsh as regular user
|
||||||
|
```
|
||||||
|
chsh
|
||||||
|
```
|
||||||
|
|
||||||
|
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
|
||||||
|
---
|
||||||
|
lib/getdef.c | 2 ++
|
||||||
|
1 files changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/lib/getdef.c b/lib/getdef.c
|
||||||
|
index a2a7e484..763d847a 100644
|
||||||
|
--- a/lib/getdef.c
|
||||||
|
+++ b/lib/getdef.c
|
||||||
|
@@ -522,6 +522,8 @@ static void def_load (void)
|
||||||
|
* syslog. The tools will just use their default values.
|
||||||
|
*/
|
||||||
|
(void)putdef_str (keys[i], value);
|
||||||
|
+
|
||||||
|
+ free(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
econf_free (keys);
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
||||||
148
backport-Require-symlink-support.patch
Normal file
148
backport-Require-symlink-support.patch
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
From dab764d0195fc16d1d39330eee8a33e8917826d8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
|
||||||
|
Date: Fri, 5 Aug 2022 17:57:24 +0200
|
||||||
|
Subject: [PATCH] Require symlink support
|
||||||
|
|
||||||
|
Require lstat(2), lchown(2), S_IFLNK and S_ISLNK from POSIX.1-2001.
|
||||||
|
|
||||||
|
Already unconditionally used in lib/tcbfuncs.c and lib/run_part.c.
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/dab764d0195fc16d1d39330eee8a33e8917826d8
|
||||||
|
|
||||||
|
---
|
||||||
|
configure.ac | 2 +-
|
||||||
|
lib/commonio.c | 2 --
|
||||||
|
lib/defines.h | 16 ----------------
|
||||||
|
libmisc/copydir.c | 10 ++--------
|
||||||
|
4 files changed, 3 insertions(+), 27 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/configure.ac b/configure.ac
|
||||||
|
index b9a2263bb..7e954c29c 100644
|
||||||
|
--- a/configure.ac
|
||||||
|
+++ b/configure.ac
|
||||||
|
@@ -53,7 +53,7 @@ AC_CHECK_HEADER([shadow.h],,[AC_MSG_ERROR([You need a libc with shadow.h])])
|
||||||
|
|
||||||
|
AC_CHECK_FUNCS(arc4random_buf l64a fchmod fchown fsync futimes getgroups \
|
||||||
|
gethostname getentropy getrandom getspnam gettimeofday getusershell \
|
||||||
|
- getutent initgroups lchown lckpwdf lstat lutimes memcpy memset \
|
||||||
|
+ getutent initgroups lckpwdf lutimes memcpy memset \
|
||||||
|
setgroups sigaction strchr updwtmp updwtmpx innetgr getpwnam_r \
|
||||||
|
getpwuid_r getgrnam_r getgrgid_r getspnam_r getaddrinfo ruserok \
|
||||||
|
dlopen)
|
||||||
|
diff --git a/lib/commonio.c b/lib/commonio.c
|
||||||
|
index 9e0fde600..80288d644 100644
|
||||||
|
--- a/lib/commonio.c
|
||||||
|
+++ b/lib/commonio.c
|
||||||
|
@@ -65,7 +65,6 @@ int lrename (const char *old, const char *new)
|
||||||
|
int res;
|
||||||
|
char *r = NULL;
|
||||||
|
|
||||||
|
-#if defined(S_ISLNK)
|
||||||
|
#ifndef __GLIBC__
|
||||||
|
char resolved_path[PATH_MAX];
|
||||||
|
#endif /* !__GLIBC__ */
|
||||||
|
@@ -82,7 +81,6 @@ int lrename (const char *old, const char *new)
|
||||||
|
new = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-#endif /* S_ISLNK */
|
||||||
|
|
||||||
|
res = rename (old, new);
|
||||||
|
|
||||||
|
diff --git a/lib/defines.h b/lib/defines.h
|
||||||
|
index 4a2b90c9e..ee33aa0da 100644
|
||||||
|
--- a/lib/defines.h
|
||||||
|
+++ b/lib/defines.h
|
||||||
|
@@ -205,22 +205,6 @@ static inline void memzero(void *ptr, size_t size)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-#ifndef S_ISLNK
|
||||||
|
-#define S_ISLNK(x) (0)
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
-#if HAVE_LCHOWN
|
||||||
|
-#define LCHOWN lchown
|
||||||
|
-#else
|
||||||
|
-#define LCHOWN chown
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
-#if HAVE_LSTAT
|
||||||
|
-#define LSTAT lstat
|
||||||
|
-#else
|
||||||
|
-#define LSTAT stat
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
#if HAVE_TERMIOS_H
|
||||||
|
# include <termios.h>
|
||||||
|
# define STTY(fd, termio) tcsetattr(fd, TCSANOW, termio)
|
||||||
|
diff --git a/libmisc/copydir.c b/libmisc/copydir.c
|
||||||
|
index 2929151db..648f562a1 100644
|
||||||
|
--- a/libmisc/copydir.c
|
||||||
|
+++ b/libmisc/copydir.c
|
||||||
|
@@ -56,14 +56,12 @@ static int copy_dir (const char *src, const char *dst,
|
||||||
|
const struct stat *statp, const struct timeval mt[],
|
||||||
|
uid_t old_uid, uid_t new_uid,
|
||||||
|
gid_t old_gid, gid_t new_gid);
|
||||||
|
-#ifdef S_IFLNK
|
||||||
|
static /*@null@*/char *readlink_malloc (const char *filename);
|
||||||
|
static int copy_symlink (const char *src, const char *dst,
|
||||||
|
unused bool reset_selinux,
|
||||||
|
const struct stat *statp, const struct timeval mt[],
|
||||||
|
uid_t old_uid, uid_t new_uid,
|
||||||
|
gid_t old_gid, gid_t new_gid);
|
||||||
|
-#endif /* S_IFLNK */
|
||||||
|
static int copy_hardlink (const char *dst,
|
||||||
|
unused bool reset_selinux,
|
||||||
|
struct link_name *lp);
|
||||||
|
@@ -223,7 +221,7 @@ int copy_tree (const char *src_root, const char *dst_root,
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (LSTAT (src_root, &sb) == -1) {
|
||||||
|
+ if (lstat (src_root, &sb) == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -364,7 +362,7 @@ static int copy_entry (const char *src, const char *dst,
|
||||||
|
struct link_name *lp;
|
||||||
|
struct timeval mt[2];
|
||||||
|
|
||||||
|
- if (LSTAT (src, &sb) == -1) {
|
||||||
|
+ if (lstat (src, &sb) == -1) {
|
||||||
|
/* If we cannot stat the file, do not care. */
|
||||||
|
} else {
|
||||||
|
#ifdef HAVE_STRUCT_STAT_ST_ATIM
|
||||||
|
@@ -396,7 +394,6 @@ static int copy_entry (const char *src, const char *dst,
|
||||||
|
old_uid, new_uid, old_gid, new_gid);
|
||||||
|
}
|
||||||
|
|
||||||
|
-#ifdef S_IFLNK
|
||||||
|
/*
|
||||||
|
* Copy any symbolic links
|
||||||
|
*/
|
||||||
|
@@ -405,7 +402,6 @@ static int copy_entry (const char *src, const char *dst,
|
||||||
|
err = copy_symlink (src, dst, reset_selinux, &sb, mt,
|
||||||
|
old_uid, new_uid, old_gid, new_gid);
|
||||||
|
}
|
||||||
|
-#endif /* S_IFLNK */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See if this is a previously copied link
|
||||||
|
@@ -498,7 +494,6 @@ static int copy_dir (const char *src, const char *dst,
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
-#ifdef S_IFLNK
|
||||||
|
/*
|
||||||
|
* readlink_malloc - wrapper for readlink
|
||||||
|
*
|
||||||
|
@@ -616,7 +611,6 @@ static int copy_symlink (const char *src, const char *dst,
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
-#endif /* S_IFLNK */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* copy_hardlink - copy a hardlink
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
From 53a17c1742a4b5fcf9280fd6dd85fc77588535c2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jeffrey Bencteux <jeffbencteux@gmail.com>
|
||||||
|
Date: Wed, 21 Jun 2023 15:12:43 +0200
|
||||||
|
Subject: [PATCH] chgpasswd: fix segfault in command-line options
|
||||||
|
|
||||||
|
Using the --sha-rounds option without first giving a crypt method via the --crypt-method option results in comparisons with a NULL pointer and thus make chgpasswd segfault:
|
||||||
|
|
||||||
|
$ chgpasswd -s 1
|
||||||
|
zsh: segmentation fault chgpasswd -s 1
|
||||||
|
|
||||||
|
Current patch add a sanity check before these comparisons to ensure there is a defined encryption method.
|
||||||
|
---
|
||||||
|
src/chgpasswd.c | 7 +++++++
|
||||||
|
1 file changed, 7 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/src/chgpasswd.c b/src/chgpasswd.c
|
||||||
|
index fe4055d8..7b773e2f 100644
|
||||||
|
--- a/src/chgpasswd.c
|
||||||
|
+++ b/src/chgpasswd.c
|
||||||
|
@@ -186,6 +186,13 @@ static void process_flags (int argc, char **argv)
|
||||||
|
case 's':
|
||||||
|
sflg = true;
|
||||||
|
bad_s = 0;
|
||||||
|
+
|
||||||
|
+ if (!crypt_method) {
|
||||||
|
+ fprintf (stderr,
|
||||||
|
+ _("%s: no crypt method defined\n"),
|
||||||
|
+ Prog);
|
||||||
|
+ usage (E_USAGE);
|
||||||
|
+ }
|
||||||
|
#if defined(USE_SHA_CRYPT)
|
||||||
|
if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512")))
|
||||||
|
&& (0 == getlong(optarg, &sha_rounds)))) {
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
||||||
97
backport-chpasswd-add-IS_CRYPT_METHOD.patch
Normal file
97
backport-chpasswd-add-IS_CRYPT_METHOD.patch
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
From 9cdb5251b6c30487a7d935a1a7827f493249479d Mon Sep 17 00:00:00 2001
|
||||||
|
From: juyin <zhuyan34@huawei.com>
|
||||||
|
Date: Sat, 2 Apr 2022 11:48:51 +0800
|
||||||
|
Subject: [PATCH] chpasswd: add IS_CRYPT_METHOD
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
Use macro IS_CRYPT_METHOD instead of ’strcmp(crypt_method, xx)==0’ to make the code more cleanup
|
||||||
|
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/9cdb5251b6c30487a7d935a1a7827f493249479d
|
||||||
|
Conflict: This patch is adapted to SM3.The pre-optimization of the get_salt function is not incorporated. Therefore, the modification related to the get_salt function is not incorporated in this patch.
|
||||||
|
---
|
||||||
|
src/chpasswd.c | 34 ++++++++++++++++++----------------
|
||||||
|
1 file changed, 18 insertions(+), 16 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/chpasswd.c b/src/chpasswd.c
|
||||||
|
index 3b30c01..cc00180 100644
|
||||||
|
--- a/src/chpasswd.c
|
||||||
|
+++ b/src/chpasswd.c
|
||||||
|
@@ -52,6 +52,8 @@
|
||||||
|
/*@-exitarg@*/
|
||||||
|
#include "exitcodes.h"
|
||||||
|
|
||||||
|
+#define IS_CRYPT_METHOD(str) ((crypt_method != NULL && strcmp(crypt_method, str) == 0) ? true : false)
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Global variables
|
||||||
|
*/
|
||||||
|
@@ -208,26 +210,26 @@ static void process_flags (int argc, char **argv)
|
||||||
|
sflg = true;
|
||||||
|
bad_s = 0;
|
||||||
|
#if defined(USE_SHA_CRYPT)
|
||||||
|
- if ( ( ((0 == strcmp (crypt_method, "SHA256")) || (0 == strcmp (crypt_method, "SHA512")))
|
||||||
|
- && (0 == getlong(optarg, &sha_rounds)))) {
|
||||||
|
+ if ((IS_CRYPT_METHOD("SHA256") || IS_CRYPT_METHOD("SHA512"))
|
||||||
|
+ && (0 == getlong(optarg, &sha_rounds))) {
|
||||||
|
bad_s = 1;
|
||||||
|
}
|
||||||
|
#endif /* USE_SHA_CRYPT */
|
||||||
|
#if defined(USE_BCRYPT)
|
||||||
|
- if (( (0 == strcmp (crypt_method, "BCRYPT"))
|
||||||
|
- && (0 == getlong(optarg, &bcrypt_rounds)))) {
|
||||||
|
+ if (IS_CRYPT_METHOD("BCRYPT")
|
||||||
|
+ && (0 == getlong(optarg, &bcrypt_rounds))) {
|
||||||
|
bad_s = 1;
|
||||||
|
}
|
||||||
|
#endif /* USE_BCRYPT */
|
||||||
|
#if defined(USE_YESCRYPT)
|
||||||
|
- if (( (0 == strcmp (crypt_method, "YESCRYPT"))
|
||||||
|
- && (0 == getlong(optarg, &yescrypt_cost)))) {
|
||||||
|
+ if (IS_CRYPT_METHOD("YESCRYPT")
|
||||||
|
+ && (0 == getlong(optarg, &yescrypt_cost))) {
|
||||||
|
bad_s = 1;
|
||||||
|
}
|
||||||
|
#endif /* USE_YESCRYPT */
|
||||||
|
#if defined(USE_SM3_CRYPT)
|
||||||
|
- if (( (0 == strcmp (crypt_method, "SM3"))
|
||||||
|
- && (0 == getlong(optarg, &sm3_rounds)))) {
|
||||||
|
+ if (IS_CRYPT_METHOD("SM3")
|
||||||
|
+ && (0 == getlong(optarg, &sm3_rounds))) {
|
||||||
|
bad_s = 1;
|
||||||
|
}
|
||||||
|
#endif /* USE_SM3_CRYPT */
|
||||||
|
@@ -275,21 +277,21 @@ static void check_flags (void)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cflg) {
|
||||||
|
- if ( (0 != strcmp (crypt_method, "DES"))
|
||||||
|
- && (0 != strcmp (crypt_method, "MD5"))
|
||||||
|
- && (0 != strcmp (crypt_method, "NONE"))
|
||||||
|
+ if ((!IS_CRYPT_METHOD("DES"))
|
||||||
|
+ &&(!IS_CRYPT_METHOD("MD5"))
|
||||||
|
+ &&(!IS_CRYPT_METHOD("NONE"))
|
||||||
|
#ifdef USE_SHA_CRYPT
|
||||||
|
- && (0 != strcmp (crypt_method, "SHA256"))
|
||||||
|
- && (0 != strcmp (crypt_method, "SHA512"))
|
||||||
|
+ &&(!IS_CRYPT_METHOD("SHA256"))
|
||||||
|
+ &&(!IS_CRYPT_METHOD("SHA512"))
|
||||||
|
#endif /* USE_SHA_CRYPT */
|
||||||
|
#ifdef USE_SM3_CRYPT
|
||||||
|
- && (0 != strcmp (crypt_method, "SM3"))
|
||||||
|
+ &&(!IS_CRYPT_METHOD("SM3"))
|
||||||
|
#endif /* USE_SM3_CRYPT */
|
||||||
|
#ifdef USE_BCRYPT
|
||||||
|
- && (0 != strcmp (crypt_method, "BCRYPT"))
|
||||||
|
+ &&(!IS_CRYPT_METHOD("BCRYPT"))
|
||||||
|
#endif /* USE_BCRYPT */
|
||||||
|
#ifdef USE_YESCRYPT
|
||||||
|
- && (0 != strcmp (crypt_method, "YESCRYPT"))
|
||||||
|
+ &&(!IS_CRYPT_METHOD("YESCRYPT"))
|
||||||
|
#endif /* USE_YESCRYPT */
|
||||||
|
) {
|
||||||
|
fprintf (stderr,
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
||||||
31
backport-chsh-Verify-that-login-shell-path-is-absolute.patch
Normal file
31
backport-chsh-Verify-that-login-shell-path-is-absolute.patch
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
From 7321ceaf69a7028a04056e548d861b291634c2d0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Samanta Navarro <ferivoz@riseup.net>
|
||||||
|
Date: Thu, 18 May 2023 11:58:19 +0000
|
||||||
|
Subject: [PATCH] chsh: Verify that login shell path is absolute
|
||||||
|
|
||||||
|
The getusershell implementation of musl returns every line within the
|
||||||
|
/etc/shells file, which even includes comments. Only consider absolute
|
||||||
|
paths for login shells.
|
||||||
|
|
||||||
|
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
|
||||||
|
---
|
||||||
|
src/chsh.c | 3 ++-
|
||||||
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/src/chsh.c b/src/chsh.c
|
||||||
|
index 639ff630..d6eca6e3 100644
|
||||||
|
--- a/src/chsh.c
|
||||||
|
+++ b/src/chsh.c
|
||||||
|
@@ -574,7 +574,8 @@ int main (int argc, char **argv)
|
||||||
|
fail_exit (1);
|
||||||
|
}
|
||||||
|
if ( !amroot
|
||||||
|
- && ( is_restricted_shell (loginsh)
|
||||||
|
+ && ( loginsh[0] != '/'
|
||||||
|
+ || is_restricted_shell (loginsh)
|
||||||
|
|| (access (loginsh, X_OK) != 0))) {
|
||||||
|
fprintf (stderr, _("%s: %s is an invalid shell\n"), Prog, loginsh);
|
||||||
|
fail_exit (1);
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
||||||
35
backport-def_load-avoid-NULL-deref.patch
Normal file
35
backport-def_load-avoid-NULL-deref.patch
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
From 419cf1f1c4721829c4d68c9e5fee112a5da5890f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Serge Hallyn <serge@hallyn.com>
|
||||||
|
Date: Fri, 19 May 2023 14:49:04 -0500
|
||||||
|
Subject: [PATCH] def_load: avoid NULL deref
|
||||||
|
|
||||||
|
If econf_getStringValue() fails, it will return an error and
|
||||||
|
set value to NULL. Look for the error and avoid dereferencing
|
||||||
|
value in that case.
|
||||||
|
|
||||||
|
Signed-off-by: Serge Hallyn <serge@hallyn.com>
|
||||||
|
---
|
||||||
|
lib/getdef.c | 7 ++++++-
|
||||||
|
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/lib/getdef.c b/lib/getdef.c
|
||||||
|
index 39cd62d5..8075821b 100644
|
||||||
|
--- a/lib/getdef.c
|
||||||
|
+++ b/lib/getdef.c
|
||||||
|
@@ -505,7 +505,12 @@ static void def_load (void)
|
||||||
|
for (size_t i = 0; i < key_number; i++) {
|
||||||
|
char *value;
|
||||||
|
|
||||||
|
- econf_getStringValue(defs_file, NULL, keys[i], &value);
|
||||||
|
+ error = econf_getStringValue(defs_file, NULL, keys[i], &value);
|
||||||
|
+ if (error) {
|
||||||
|
+ SYSLOG ((LOG_CRIT, "failed reading key %zu from econf [%s]",
|
||||||
|
+ i, econf_errString(error)));
|
||||||
|
+ exit (EXIT_FAILURE);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Store the value in def_table.
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
||||||
142
backport-gpasswd-1-Fix-password-leak.patch
Normal file
142
backport-gpasswd-1-Fix-password-leak.patch
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
From 65c88a43a23c2391dcc90c0abda3e839e9c57904 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Alejandro Colomar <alx@kernel.org>
|
||||||
|
Date: Sat, 10 Jun 2023 16:20:05 +0200
|
||||||
|
Subject: [PATCH] gpasswd(1): Fix password leak
|
||||||
|
|
||||||
|
How to trigger this password leak?
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
When gpasswd(1) asks for the new password, it asks twice (as is usual
|
||||||
|
for confirming the new password). Each of those 2 password prompts
|
||||||
|
uses agetpass() to get the password. If the second agetpass() fails,
|
||||||
|
the first password, which has been copied into the 'static' buffer
|
||||||
|
'pass' via STRFCPY(), wasn't being zeroed.
|
||||||
|
|
||||||
|
agetpass() is defined in <./libmisc/agetpass.c> (around line 91), and
|
||||||
|
can fail for any of the following reasons:
|
||||||
|
|
||||||
|
- malloc(3) or readpassphrase(3) failure.
|
||||||
|
|
||||||
|
These are going to be difficult to trigger. Maybe getting the system
|
||||||
|
to the limits of memory utilization at that exact point, so that the
|
||||||
|
next malloc(3) gets ENOMEM, and possibly even the OOM is triggered.
|
||||||
|
About readpassphrase(3), ENFILE and EINTR seem the only plausible
|
||||||
|
ones, and EINTR probably requires privilege or being the same user;
|
||||||
|
but I wouldn't discard ENFILE so easily, if a process starts opening
|
||||||
|
files.
|
||||||
|
|
||||||
|
- The password is longer than PASS_MAX.
|
||||||
|
|
||||||
|
The is plausible with physical access. However, at that point, a
|
||||||
|
keylogger will be a much simpler attack.
|
||||||
|
|
||||||
|
And, the attacker must be able to know when the second password is being
|
||||||
|
introduced, which is not going to be easy.
|
||||||
|
|
||||||
|
How to read the password after the leak?
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Provoking the leak yourself at the right point by entering a very long
|
||||||
|
password is easy, and inspecting the process stack at that point should
|
||||||
|
be doable. Try to find some consistent patterns.
|
||||||
|
|
||||||
|
Then, search for those patterns in free memory, right after the victim
|
||||||
|
leaks their password.
|
||||||
|
|
||||||
|
Once you get the leak, a program should read all the free memory
|
||||||
|
searching for patterns that gpasswd(1) leaves nearby the leaked
|
||||||
|
password.
|
||||||
|
|
||||||
|
On 6/10/23 03:14, Seth Arnold wrote:
|
||||||
|
> An attacker process wouldn't be able to use malloc(3) for this task.
|
||||||
|
> There's a handful of tools available for userspace to allocate memory:
|
||||||
|
>
|
||||||
|
> - brk / sbrk
|
||||||
|
> - mmap MAP_ANONYMOUS
|
||||||
|
> - mmap /dev/zero
|
||||||
|
> - mmap some other file
|
||||||
|
> - shm_open
|
||||||
|
> - shmget
|
||||||
|
>
|
||||||
|
> Most of these return only pages of zeros to a process. Using mmap of an
|
||||||
|
> existing file, you can get some of the contents of the file demand-loaded
|
||||||
|
> into the memory space on the first use.
|
||||||
|
>
|
||||||
|
> The MAP_UNINITIALIZED flag only works if the kernel was compiled with
|
||||||
|
> CONFIG_MMAP_ALLOW_UNINITIALIZED. This is rare.
|
||||||
|
>
|
||||||
|
> malloc(3) doesn't zero memory, to our collective frustration, but all the
|
||||||
|
> garbage in the allocations is from previous allocations in the current
|
||||||
|
> process. It isn't leftover from other processes.
|
||||||
|
>
|
||||||
|
> The avenues available for reading the memory:
|
||||||
|
> - /dev/mem and /dev/kmem (requires root, not available with Secure Boot)
|
||||||
|
> - /proc/pid/mem (requires ptrace privileges, mediated by YAMA)
|
||||||
|
> - ptrace (requires ptrace privileges, mediated by YAMA)
|
||||||
|
> - causing memory to be swapped to disk, and then inspecting the swap
|
||||||
|
>
|
||||||
|
> These all require a certain amount of privileges.
|
||||||
|
|
||||||
|
How to fix it?
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
memzero(), which internally calls explicit_bzero(3), or whatever
|
||||||
|
alternative the system provides with a slightly different name, will
|
||||||
|
make sure that the buffer is zeroed in memory, and optimizations are not
|
||||||
|
allowed to impede this zeroing.
|
||||||
|
|
||||||
|
This is not really 100% effective, since compilers may place copies of
|
||||||
|
the string somewhere hidden in the stack. Those copies won't get zeroed
|
||||||
|
by explicit_bzero(3). However, that's arguably a compiler bug, since
|
||||||
|
compilers should make everything possible to avoid optimizing strings
|
||||||
|
that are later passed to explicit_bzero(3). But we all know that
|
||||||
|
sometimes it's impossible to have perfect knowledge in the compiler, so
|
||||||
|
this is plausible. Nevertheless, there's nothing we can do against such
|
||||||
|
issues, except minimizing the time such passwords are stored in plain
|
||||||
|
text.
|
||||||
|
|
||||||
|
Security concerns
|
||||||
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
We believe this isn't easy to exploit. Nevertheless, and since the fix
|
||||||
|
is trivial, this fix should probably be applied soon, and backported to
|
||||||
|
all supported distributions, to prevent someone else having more
|
||||||
|
imagination than us to find a way.
|
||||||
|
|
||||||
|
Affected versions
|
||||||
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
All. Bug introduced in shadow 19990709. That's the second commit in
|
||||||
|
the git history.
|
||||||
|
|
||||||
|
Fixes: 45c6603cc86c ("[svn-upgrade] Integrating new upstream version, shadow (19990709)")
|
||||||
|
Reported-by: Alejandro Colomar <alx@kernel.org>
|
||||||
|
Cc: Serge Hallyn <serge@hallyn.com>
|
||||||
|
Cc: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
Cc: Seth Arnold <seth.arnold@canonical.com>
|
||||||
|
Cc: Christian Brauner <christian@brauner.io>
|
||||||
|
Cc: Balint Reczey <rbalint@debian.org>
|
||||||
|
Cc: Sam James <sam@gentoo.org>
|
||||||
|
Cc: David Runge <dvzrv@archlinux.org>
|
||||||
|
Cc: Andreas Jaeger <aj@suse.de>
|
||||||
|
Cc: <~hallyn/shadow@lists.sr.ht>
|
||||||
|
Signed-off-by: Alejandro Colomar <alx@kernel.org>
|
||||||
|
---
|
||||||
|
src/gpasswd.c | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/src/gpasswd.c b/src/gpasswd.c
|
||||||
|
index 609fe0a4..3b76ff8e 100644
|
||||||
|
--- a/src/gpasswd.c
|
||||||
|
+++ b/src/gpasswd.c
|
||||||
|
@@ -898,6 +898,7 @@ static void change_passwd (struct group *gr)
|
||||||
|
strzero (cp);
|
||||||
|
cp = getpass (_("Re-enter new password: "));
|
||||||
|
if (NULL == cp) {
|
||||||
|
+ memzero (pass, sizeof pass);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
||||||
29
backport-lib-btrfs-avoid-NULL-dereference.patch
Normal file
29
backport-lib-btrfs-avoid-NULL-dereference.patch
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
From 54ab542887994f8b6e5411469d6867e3a2e58800 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
|
||||||
|
Date: Thu, 26 Jan 2023 21:03:56 +0100
|
||||||
|
Subject: [PATCH] lib/btrfs: avoid NULL-dereference
|
||||||
|
|
||||||
|
btrfs.c:42:13: warning: use of NULL 'cmd' where non-null expected [CWE-476] [-Wanalyzer-null-argument]
|
||||||
|
|
||||||
|
Reviewed-by: Alejandro Colomar <alx@kernel.org>
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/54ab542887994f8b6e5411469d6867e3a2e58800
|
||||||
|
|
||||||
|
---
|
||||||
|
libmisc/btrfs.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmisc/btrfs.c b/libmisc/btrfs.c
|
||||||
|
index a2563f7c3..03915981c 100644
|
||||||
|
--- a/libmisc/btrfs.c
|
||||||
|
+++ b/libmisc/btrfs.c
|
||||||
|
@@ -39,7 +39,7 @@ static int run_btrfs_subvolume_cmd(const char *subcmd, const char *arg1, const c
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
- if (access(cmd, X_OK)) {
|
||||||
|
+ if (!cmd || access(cmd, X_OK)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
70
backport-lib-check-NULL-before-freeing-passwd-data.patch
Normal file
70
backport-lib-check-NULL-before-freeing-passwd-data.patch
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
From d594243fbbdabc73fdee50886f6dd11867b5cfab Mon Sep 17 00:00:00 2001
|
||||||
|
From: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
Date: Thu, 18 Nov 2021 16:48:26 +0100
|
||||||
|
Subject: [PATCH] lib: check NULL before freeing passwd data
|
||||||
|
|
||||||
|
Add an additional NULL check condition in spw_free() and pw_free() to
|
||||||
|
avoid freeing an already empty pointer.
|
||||||
|
|
||||||
|
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/d594243fbbdabc73fdee50886f6dd11867b5cfab
|
||||||
|
|
||||||
|
---
|
||||||
|
lib/pwmem.c | 18 ++++++++++--------
|
||||||
|
lib/shadowmem.c | 12 +++++++-----
|
||||||
|
2 files changed, 17 insertions(+), 13 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/lib/pwmem.c b/lib/pwmem.c
|
||||||
|
index 17d2eb219..9f184d5e1 100644
|
||||||
|
--- a/lib/pwmem.c
|
||||||
|
+++ b/lib/pwmem.c
|
||||||
|
@@ -93,14 +93,16 @@
|
||||||
|
|
||||||
|
void pw_free (/*@out@*/ /*@only@*/struct passwd *pwent)
|
||||||
|
{
|
||||||
|
- free (pwent->pw_name);
|
||||||
|
- if (pwent->pw_passwd) {
|
||||||
|
- memzero (pwent->pw_passwd, strlen (pwent->pw_passwd));
|
||||||
|
- free (pwent->pw_passwd);
|
||||||
|
+ if (pwent != NULL) {
|
||||||
|
+ free (pwent->pw_name);
|
||||||
|
+ if (pwent->pw_passwd) {
|
||||||
|
+ memzero (pwent->pw_passwd, strlen (pwent->pw_passwd));
|
||||||
|
+ free (pwent->pw_passwd);
|
||||||
|
+ }
|
||||||
|
+ free (pwent->pw_gecos);
|
||||||
|
+ free (pwent->pw_dir);
|
||||||
|
+ free (pwent->pw_shell);
|
||||||
|
+ free (pwent);
|
||||||
|
}
|
||||||
|
- free (pwent->pw_gecos);
|
||||||
|
- free (pwent->pw_dir);
|
||||||
|
- free (pwent->pw_shell);
|
||||||
|
- free (pwent);
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/lib/shadowmem.c b/lib/shadowmem.c
|
||||||
|
index 8989598f8..1d047cc04 100644
|
||||||
|
--- a/lib/shadowmem.c
|
||||||
|
+++ b/lib/shadowmem.c
|
||||||
|
@@ -79,11 +79,13 @@
|
||||||
|
|
||||||
|
void spw_free (/*@out@*/ /*@only@*/struct spwd *spent)
|
||||||
|
{
|
||||||
|
- free (spent->sp_namp);
|
||||||
|
- if (NULL != spent->sp_pwdp) {
|
||||||
|
- memzero (spent->sp_pwdp, strlen (spent->sp_pwdp));
|
||||||
|
- free (spent->sp_pwdp);
|
||||||
|
+ if (spent != NULL) {
|
||||||
|
+ free (spent->sp_namp);
|
||||||
|
+ if (NULL != spent->sp_pwdp) {
|
||||||
|
+ memzero (spent->sp_pwdp, strlen (spent->sp_pwdp));
|
||||||
|
+ free (spent->sp_pwdp);
|
||||||
|
+ }
|
||||||
|
+ free (spent);
|
||||||
|
}
|
||||||
|
- free (spent);
|
||||||
|
}
|
||||||
|
|
||||||
58
backport-libmisc-minimum-id-check-for-system-accounts.patch
Normal file
58
backport-libmisc-minimum-id-check-for-system-accounts.patch
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
From d324c6776b3a1d4ac22bced543f72dc5dd366927 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
Date: Thu, 6 Oct 2022 11:21:18 +0200
|
||||||
|
Subject: [PATCH] libmisc: minimum id check for system accounts
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
The minimum id allocation for system accounts shouldn't be 0 as this is
|
||||||
|
reserved for root.
|
||||||
|
|
||||||
|
Signed-off-by: Tomáš Mráz <tm@t8m.info>
|
||||||
|
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/d324c6776b3a1d4ac22bced543f72dc5dd366927
|
||||||
|
|
||||||
|
---
|
||||||
|
libmisc/find_new_gid.c | 7 +++++++
|
||||||
|
libmisc/find_new_uid.c | 7 +++++++
|
||||||
|
2 files changed, 14 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/libmisc/find_new_gid.c b/libmisc/find_new_gid.c
|
||||||
|
index 666b61078..65ab5d013 100644
|
||||||
|
--- a/libmisc/find_new_gid.c
|
||||||
|
+++ b/libmisc/find_new_gid.c
|
||||||
|
@@ -60,6 +60,13 @@ static int get_ranges (bool sys_group, gid_t *min_id, gid_t *max_id,
|
||||||
|
(unsigned long) *max_id);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
+ /*
|
||||||
|
+ * Zero is reserved for root and the allocation algorithm does not
|
||||||
|
+ * work right with it.
|
||||||
|
+ */
|
||||||
|
+ if (*min_id == 0) {
|
||||||
|
+ *min_id = (gid_t) 1;
|
||||||
|
+ }
|
||||||
|
} else {
|
||||||
|
/* Non-system groups */
|
||||||
|
|
||||||
|
diff --git a/libmisc/find_new_uid.c b/libmisc/find_new_uid.c
|
||||||
|
index 322d15ab7..5f7e74b53 100644
|
||||||
|
--- a/libmisc/find_new_uid.c
|
||||||
|
+++ b/libmisc/find_new_uid.c
|
||||||
|
@@ -60,6 +60,13 @@ static int get_ranges (bool sys_user, uid_t *min_id, uid_t *max_id,
|
||||||
|
(unsigned long) *max_id);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
+ /*
|
||||||
|
+ * Zero is reserved for root and the allocation algorithm does not
|
||||||
|
+ * work right with it.
|
||||||
|
+ */
|
||||||
|
+ if (*min_id == 0) {
|
||||||
|
+ *min_id = (uid_t) 1;
|
||||||
|
+ }
|
||||||
|
} else {
|
||||||
|
/* Non-system users */
|
||||||
|
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
From 02b200c9aa501ad4e1651c553cea1aaf9e5e0f4f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Serge Hallyn <serge@hallyn.com>
|
||||||
|
Date: Sat, 14 Aug 2021 14:24:03 -0500
|
||||||
|
Subject: [PATCH] man/po/Makefile.in: switch from xml2po to itstool
|
||||||
|
|
||||||
|
xml2po is deprecated. We've previously replaced xml2po with
|
||||||
|
itstool in man/generate_translations.mak, but there was still
|
||||||
|
an instance of it that only is exercised for 'make dist'.
|
||||||
|
Update that one. Now 'make dist' succeeds on a ubuntu focal
|
||||||
|
or newer host where xml2po is not available.
|
||||||
|
|
||||||
|
Signed-off-by: Serge Hallyn <serge@hallyn.com>
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/02b200c9aa501ad4e1651c553cea1aaf9e5e0f4f
|
||||||
|
|
||||||
|
---
|
||||||
|
man/po/Makefile.in | 14 +++++++++++---
|
||||||
|
1 file changed, 11 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/man/po/Makefile.in b/man/po/Makefile.in
|
||||||
|
index deaa87058..f194957b4 100644
|
||||||
|
--- a/man/po/Makefile.in
|
||||||
|
+++ b/man/po/Makefile.in
|
||||||
|
@@ -90,9 +90,17 @@ $(DOMAIN).pot-update: $(XMLFILES) $(srcdir)/XMLFILES remove-potcdate.sed
|
||||||
|
@set -e; tmpdir=`pwd`; \
|
||||||
|
echo "cd $(top_srcdir)/man"; \
|
||||||
|
cd $(top_srcdir)/man; \
|
||||||
|
- echo "xml2po --expand-all-entities -o $$tmpdir/$(DOMAIN).po $(notdir $(XMLFILES))"; \
|
||||||
|
- xml2po --expand-all-entities -o $$tmpdir/$(DOMAIN).po $(notdir $(XMLFILES)); \
|
||||||
|
- cd $$tmpdir
|
||||||
|
+ files=""; \
|
||||||
|
+ for file in $(notdir $(XMLFILES)); do \
|
||||||
|
+ if grep -q SHADOW-CONFIG-HERE $$file ; then \
|
||||||
|
+ sed -e 's/^<!-- SHADOW-CONFIG-HERE -->/<!ENTITY % config SYSTEM "config.xml">%config;/' $$file > $$file.out; \
|
||||||
|
+ else \
|
||||||
|
+ sed -e 's/^\(<!DOCTYPE .*docbookx.dtd"\)>/\1 [<!ENTITY % config SYSTEM "config.xml">%config;]>/' $$file > $$file.out; \
|
||||||
|
+ fi; \
|
||||||
|
+ files="$$files $$file.out"; \
|
||||||
|
+ done; \
|
||||||
|
+ itstool -d -o $$tmpdir/$(DOMAIN).po $$files; \
|
||||||
|
+ cd $$tmpdir; \
|
||||||
|
test ! -f $(DOMAIN).po || { \
|
||||||
|
if test -f $(srcdir)/$(DOMAIN).pot; then \
|
||||||
|
sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \
|
||||||
60
backport-newgrp-fix-potential-string-injection.patch
Normal file
60
backport-newgrp-fix-potential-string-injection.patch
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
From 9df4801e0b65073cc8a9031b22a73532ef7fdc2c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Vegard Nossum <vegard.nossum@oracle.com>
|
||||||
|
Date: Fri, 21 Jul 2023 14:55:19 +0200
|
||||||
|
Subject: [PATCH] newgrp: fix potential string injection
|
||||||
|
|
||||||
|
Since newgrp is setuid-root, any write() system calls it does in order
|
||||||
|
to print error messages will be done as the root user.
|
||||||
|
|
||||||
|
Unprivileged users can get newgrp to print essentially arbitrary strings
|
||||||
|
to any open file in this way by passing those strings as argv[0] when
|
||||||
|
calling execve(). For example:
|
||||||
|
|
||||||
|
$ setpid() { (exec -a $1$'\n:' newgrp '' 2>/proc/sys/kernel/ns_last_pid & wait) >/dev/null; }
|
||||||
|
$ setpid 31000
|
||||||
|
$ readlink /proc/self
|
||||||
|
31001
|
||||||
|
|
||||||
|
This is not a vulnerability in newgrp; it is a bug in the Linux kernel.
|
||||||
|
|
||||||
|
However, this type of bug is not new [1] and it makes sense to try to
|
||||||
|
mitigate these types of bugs in userspace where possible.
|
||||||
|
|
||||||
|
[1]: https://lwn.net/Articles/476947/
|
||||||
|
|
||||||
|
Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
|
||||||
|
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/9df4801e0b65073cc8a9031b22a73532ef7fdc2c
|
||||||
|
Conflict: NA
|
||||||
|
---
|
||||||
|
src/newgrp.c | 13 ++++++++++---
|
||||||
|
1 file changed, 10 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/newgrp.c b/src/newgrp.c
|
||||||
|
index babb28e9..f786a96f 100644
|
||||||
|
--- a/src/newgrp.c
|
||||||
|
+++ b/src/newgrp.c
|
||||||
|
@@ -417,10 +417,17 @@ int main (int argc, char **argv)
|
||||||
|
* but we do not need to restore the previous process persona and we
|
||||||
|
* don't need to re-exec anything. -- JWP
|
||||||
|
*/
|
||||||
|
- Prog = Basename (argv[0]);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Ensure that "Prog" is always either "newgrp" or "sg" to avoid
|
||||||
|
+ * injecting arbitrary strings into our stderr/stdout, as this can
|
||||||
|
+ * be an exploit vector.
|
||||||
|
+ */
|
||||||
|
+ is_newgrp = (strcmp (Basename (argv[0]), "newgrp") == 0);
|
||||||
|
+ Prog = is_newgrp ? "newgrp" : "sg";
|
||||||
|
+
|
||||||
|
shadow_logfd = stderr;
|
||||||
|
- is_newgrp = (strcmp (Prog, "newgrp") == 0);
|
||||||
|
- OPENLOG (is_newgrp ? "newgrp" : "sg");
|
||||||
|
+ OPENLOG (Prog);
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
||||||
40
backport-process_prefix_flag-Drop-privileges.patch
Normal file
40
backport-process_prefix_flag-Drop-privileges.patch
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
From 812f934e77700afedbf5e929b282f29a47b2d9c6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Samanta Navarro <ferivoz@riseup.net>
|
||||||
|
Date: Thu, 18 May 2023 11:56:17 +0000
|
||||||
|
Subject: [PATCH] process_prefix_flag: Drop privileges
|
||||||
|
|
||||||
|
Using --prefix in a setuid binary is quite dangerous. An unprivileged
|
||||||
|
user could prepare a custom shadow file in home directory. During a data
|
||||||
|
race the user could exchange directories with links which could lead to
|
||||||
|
exchange of shadow file in system's /etc directory.
|
||||||
|
|
||||||
|
This could be used for local privilege escalation.
|
||||||
|
|
||||||
|
Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
|
||||||
|
---
|
||||||
|
libmisc/prefix_flag.c | 9 +++++++++
|
||||||
|
1 file changed, 9 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/libmisc/prefix_flag.c b/libmisc/prefix_flag.c
|
||||||
|
index 56243f2e..d7acb9ca 100644
|
||||||
|
--- a/libmisc/prefix_flag.c
|
||||||
|
+++ b/libmisc/prefix_flag.c
|
||||||
|
@@ -85,6 +85,15 @@ extern const char* process_prefix_flag (const char* short_opt, int argc, char **
|
||||||
|
|
||||||
|
|
||||||
|
if (prefix != NULL) {
|
||||||
|
+ /* Drop privileges */
|
||||||
|
+ if ( (setregid (getgid (), getgid ()) != 0)
|
||||||
|
+ || (setreuid (getuid (), getuid ()) != 0)) {
|
||||||
|
+ fprintf (shadow_logfd,
|
||||||
|
+ _("%s: failed to drop privileges (%s)\n"),
|
||||||
|
+ Prog, strerror (errno));
|
||||||
|
+ exit (EXIT_FAILURE);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if ( prefix[0] == '\0' || !strcmp(prefix, "/"))
|
||||||
|
return ""; /* if prefix is "/" then we ignore the flag option */
|
||||||
|
/* should we prevent symbolic link from being used as a prefix? */
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
||||||
125
backport-run_parts-for-groupadd-and-groupdel.patch
Normal file
125
backport-run_parts-for-groupadd-and-groupdel.patch
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
From 4e1f674c41724dd96ad2c3a0c02ac9f6666697ba Mon Sep 17 00:00:00 2001
|
||||||
|
From: ed neville <ed@s5h.net>
|
||||||
|
Date: Mon, 27 Mar 2023 20:23:03 +0100
|
||||||
|
Subject: [PATCH] run_parts for groupadd and groupdel
|
||||||
|
|
||||||
|
run_parts currently exists in useradd and userdel, this commit mirrors
|
||||||
|
the functionality with groupadd and groupdel
|
||||||
|
|
||||||
|
Hook for group{add,del} to include killing processes that have group
|
||||||
|
membership that would no longer exist to avoid membership ID reuse.
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/4e1f674c41724dd96ad2c3a0c02ac9f6666697ba
|
||||||
|
|
||||||
|
---
|
||||||
|
.../groupdel-pre.d/01-kill_group_procs.sh | 26 +++++++++++++++++++
|
||||||
|
src/groupadd.c | 11 ++++++++
|
||||||
|
src/groupdel.c | 11 ++++++++
|
||||||
|
3 files changed, 48 insertions(+)
|
||||||
|
create mode 100644 etc/shadow-maint/groupdel-pre.d/01-kill_group_procs.sh
|
||||||
|
|
||||||
|
diff --git a/etc/shadow-maint/groupdel-pre.d/01-kill_group_procs.sh b/etc/shadow-maint/groupdel-pre.d/01-kill_group_procs.sh
|
||||||
|
new file mode 100644
|
||||||
|
index 000000000..10db52794
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/etc/shadow-maint/groupdel-pre.d/01-kill_group_procs.sh
|
||||||
|
@@ -0,0 +1,26 @@
|
||||||
|
+#!/bin/sh
|
||||||
|
+
|
||||||
|
+PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||||
|
+GROUPID=`awk -F: '$1 == "'"${SUBJECT}"'" { print $3 }' /etc/group`
|
||||||
|
+
|
||||||
|
+if [ "${GROUPID}" = "" ]; then
|
||||||
|
+ exit 0
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+for status in /proc/*/status; do
|
||||||
|
+ # either this isn't a process or its already dead since expanding the list
|
||||||
|
+ [ -f "$status" ] || continue
|
||||||
|
+
|
||||||
|
+ tbuf=${status%/status}
|
||||||
|
+ pid=${tbuf#/proc/}
|
||||||
|
+ case "$pid" in
|
||||||
|
+ "$$") continue;;
|
||||||
|
+ [0-9]*) :;;
|
||||||
|
+ *) continue
|
||||||
|
+ esac
|
||||||
|
+
|
||||||
|
+ grep -q '^Groups:.*\b'"${GROUPID}"'\b.*' "/proc/$pid/status" || continue
|
||||||
|
+
|
||||||
|
+ kill -9 "$pid" || echo "cannot kill $pid" 1>&2
|
||||||
|
+done
|
||||||
|
+
|
||||||
|
diff --git a/src/groupadd.c b/src/groupadd.c
|
||||||
|
index 311421014..2eda1c680 100644
|
||||||
|
--- a/src/groupadd.c
|
||||||
|
+++ b/src/groupadd.c
|
||||||
|
@@ -34,6 +34,7 @@
|
||||||
|
#ifdef SHADOWGRP
|
||||||
|
#include "sgroupio.h"
|
||||||
|
#endif
|
||||||
|
+#include "run_part.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* exit status values
|
||||||
|
@@ -603,6 +604,11 @@ int main (int argc, char **argv)
|
||||||
|
|
||||||
|
check_perms ();
|
||||||
|
|
||||||
|
+ if (run_parts ("/etc/shadow-maint/groupadd-pre.d", group_name,
|
||||||
|
+ "groupadd")) {
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
#ifdef SHADOWGRP
|
||||||
|
is_shadow_grp = sgr_file_present ();
|
||||||
|
#endif
|
||||||
|
@@ -621,6 +627,11 @@ int main (int argc, char **argv)
|
||||||
|
|
||||||
|
grp_update ();
|
||||||
|
close_files ();
|
||||||
|
+ if (run_parts ("/etc/shadow-maint/groupadd-post.d", group_name,
|
||||||
|
+ "groupadd")) {
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
|
||||||
|
nscd_flush_cache ("group");
|
||||||
|
sssd_flush_cache (SSSD_DB_GROUP);
|
||||||
|
diff --git a/src/groupdel.c b/src/groupdel.c
|
||||||
|
index fdccf5e15..bae4367ba 100644
|
||||||
|
--- a/src/groupdel.c
|
||||||
|
+++ b/src/groupdel.c
|
||||||
|
@@ -32,6 +32,7 @@
|
||||||
|
#ifdef SHADOWGRP
|
||||||
|
#include "sgroupio.h"
|
||||||
|
#endif
|
||||||
|
+#include "run_part.h"
|
||||||
|
/*
|
||||||
|
* Global variables
|
||||||
|
*/
|
||||||
|
@@ -461,6 +462,11 @@ int main (int argc, char **argv)
|
||||||
|
group_busy (group_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (run_parts ("/etc/shadow-maint/groupdel-pre.d", group_name,
|
||||||
|
+ "groupdel")) {
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Do the hard stuff - open the files, delete the group entries,
|
||||||
|
* then close and update the files.
|
||||||
|
@@ -471,6 +477,11 @@ int main (int argc, char **argv)
|
||||||
|
|
||||||
|
close_files ();
|
||||||
|
|
||||||
|
+ if (run_parts ("/etc/shadow-maint/groupdel-post.d", group_name,
|
||||||
|
+ "groupdel")) {
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
nscd_flush_cache ("group");
|
||||||
|
sssd_flush_cache (SSSD_DB_GROUP);
|
||||||
|
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
From dcca8653a54b5a03b0234238dbc6388f6b59adc3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: ed neville <ed@s5h.net>
|
||||||
|
Date: Fri, 17 Dec 2021 14:29:48 +0000
|
||||||
|
Subject: [PATCH] script to kill subjects processes from userdel
|
||||||
|
|
||||||
|
Closes #404
|
||||||
|
Closes #317
|
||||||
|
|
||||||
|
Signed-off-by: ed neville <ed@s5h.net>
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/dcca8653a54b5a03b0234238dbc6388f6b59adc3
|
||||||
|
---
|
||||||
|
.../userdel-pre.d/01-kill_user_procs.sh | 28 +++++++++++++++++++
|
||||||
|
1 file changed, 28 insertions(+)
|
||||||
|
create mode 100755 etc/shadow-maint/userdel-pre.d/01-kill_user_procs.sh
|
||||||
|
|
||||||
|
diff --git a/etc/shadow-maint/userdel-pre.d/01-kill_user_procs.sh b/etc/shadow-maint/userdel-pre.d/01-kill_user_procs.sh
|
||||||
|
new file mode 100755
|
||||||
|
index 00000000..ca481b1b
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/etc/shadow-maint/userdel-pre.d/01-kill_user_procs.sh
|
||||||
|
@@ -0,0 +1,28 @@
|
||||||
|
+#!/bin/sh
|
||||||
|
+
|
||||||
|
+PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||||
|
+
|
||||||
|
+# Check user exists, and if so, send sigkill to processes that the user owns
|
||||||
|
+
|
||||||
|
+RUNNING=`ps -eo user | grep -Fx "$SUBJECT" | wc -l`
|
||||||
|
+
|
||||||
|
+# if the user does not exist, RUNNING will be 0
|
||||||
|
+
|
||||||
|
+if [ "${RUNNING}x" = "0x" ]; then
|
||||||
|
+ exit 0
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+ls -1 /proc | while IFS= read -r PROC; do
|
||||||
|
+ echo "$PROC" | grep -E '^[0-9]+$' >/dev/null
|
||||||
|
+ if [ $? -ne 0 ]; then
|
||||||
|
+ continue
|
||||||
|
+ fi
|
||||||
|
+ if [ -d "/proc/${PROC}" ]; then
|
||||||
|
+ USR=`stat -c "%U" /proc/${PROC}`
|
||||||
|
+ if [ "${USR}" = "${SUBJECT}" ]; then
|
||||||
|
+ echo "Killing ${SUBJECT} owned ${PROC}"
|
||||||
|
+ kill -9 "${PROC}"
|
||||||
|
+ fi
|
||||||
|
+ fi
|
||||||
|
+done
|
||||||
|
+
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
From 7bced397c9fd66965753e5fc0fd3dfa535ca1c9b Mon Sep 17 00:00:00 2001
|
||||||
|
From: xiongshenglan <xiongshenglan@huawei.com>
|
||||||
|
Date: Wed, 19 Jul 2023 15:13:06 +0800
|
||||||
|
Subject: [PATCH] shadow userdel: add the adaptation to the busybox ps in
|
||||||
|
01-kill_user_procs.sh
|
||||||
|
|
||||||
|
In some embedded systems, users only use the ps
|
||||||
|
provided by the busybox. But the ps provided by
|
||||||
|
the busybox does not support the -eo option by
|
||||||
|
default. As a result, an error is reported when
|
||||||
|
the userdel is used. So add a judgment on ps.
|
||||||
|
If there is no ps -eo, traverse the process directly.
|
||||||
|
|
||||||
|
The error information is as follows:
|
||||||
|
# userdel xsl
|
||||||
|
ps: invalid option -- 'e'
|
||||||
|
|
||||||
|
Signed-off-by: xiongshenglan <xiongshenglan@huawei.com>
|
||||||
|
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/7bced397c9fd66965753e5fc0fd3dfa535ca1c9b
|
||||||
|
Conflict: NA
|
||||||
|
---
|
||||||
|
.../userdel-pre.d/01-kill_user_procs.sh | 15 +++++++++------
|
||||||
|
1 file changed, 9 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/etc/shadow-maint/userdel-pre.d/01-kill_user_procs.sh b/etc/shadow-maint/userdel-pre.d/01-kill_user_procs.sh
|
||||||
|
index ca481b1b..d2d7ef26 100755
|
||||||
|
--- a/etc/shadow-maint/userdel-pre.d/01-kill_user_procs.sh
|
||||||
|
+++ b/etc/shadow-maint/userdel-pre.d/01-kill_user_procs.sh
|
||||||
|
@@ -4,14 +4,17 @@ PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||||
|
|
||||||
|
# Check user exists, and if so, send sigkill to processes that the user owns
|
||||||
|
|
||||||
|
-RUNNING=`ps -eo user | grep -Fx "$SUBJECT" | wc -l`
|
||||||
|
-
|
||||||
|
-# if the user does not exist, RUNNING will be 0
|
||||||
|
-
|
||||||
|
-if [ "${RUNNING}x" = "0x" ]; then
|
||||||
|
- exit 0
|
||||||
|
+ps -eo user >/dev/null 2>&1
|
||||||
|
+if [ $? -eq 0 ]; then
|
||||||
|
+ RUNNING=`ps -eo user | grep -Fx "$SUBJECT" | wc -l`
|
||||||
|
+ # if the user does not exist, RUNNING will be 0
|
||||||
|
+ if [ "${RUNNING}x" = "0x" ]; then
|
||||||
|
+ exit 0
|
||||||
|
+ fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
+# If there is no ps -eo, traverse the process directly.
|
||||||
|
+
|
||||||
|
ls -1 /proc | while IFS= read -r PROC; do
|
||||||
|
echo "$PROC" | grep -E '^[0-9]+$' >/dev/null
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
||||||
32
backport-src-passwd-add-overflow-check.patch
Normal file
32
backport-src-passwd-add-overflow-check.patch
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
From 2d188a9987789f019dae2d46c50578a474ab2bdd Mon Sep 17 00:00:00 2001
|
||||||
|
From: Tobias Stoeckmann <tobias@stoeckmann.org>
|
||||||
|
Date: Wed, 20 Dec 2023 20:48:54 +0100
|
||||||
|
Subject: [PATCH] src/passwd.c: Add overflow check
|
||||||
|
|
||||||
|
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
|
||||||
|
Link: <https://github.com/shadow-maint/shadow/pull/876>
|
||||||
|
Co-developed-by: Alejandro Colomar <alx@kernel.org>
|
||||||
|
Signed-off-by: Alejandro Colomar <alx@kernel.org>
|
||||||
|
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/2d188a9987789f019dae2d46c50578a474ab2bdd
|
||||||
|
Conflict: NA
|
||||||
|
---
|
||||||
|
src/passwd.c | 5 +++--
|
||||||
|
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/passwd.c b/src/passwd.c
|
||||||
|
index a24e62dfd..f494a9257 100644
|
||||||
|
--- a/src/passwd.c
|
||||||
|
+++ b/src/passwd.c
|
||||||
|
@@ -387,8 +387,9 @@ static void check_password (const struct passwd *pw, const struct spwd *sp)
|
||||||
|
long now, ok;
|
||||||
|
now = time(NULL) / DAY;
|
||||||
|
ok = sp->sp_lstchg;
|
||||||
|
- if (sp->sp_min > 0) {
|
||||||
|
- ok += sp->sp_min;
|
||||||
|
+ if ( (sp->sp_min > 0)
|
||||||
|
+ && __builtin_add_overflow(ok, sp->sp_min, &ok)) {
|
||||||
|
+ ok = LONG_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (now < ok) {
|
||||||
61
backport-src-passwd.c-Switch-to-day-precision.patch
Normal file
61
backport-src-passwd.c-Switch-to-day-precision.patch
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
From 3b5ba41d3e9dfc3bf058f0f31529c08201265241 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Tobias Stoeckmann <tobias@stoeckmann.org>
|
||||||
|
Date: Thu, 14 Dec 2023 11:54:00 +0100
|
||||||
|
Subject: [PATCH] src/passwd.c: Switch to day precision
|
||||||
|
|
||||||
|
The size of time_t varies across systems, but since data type long is
|
||||||
|
more than enough to calculate with days (precision of shadow file),
|
||||||
|
use it instead.
|
||||||
|
|
||||||
|
Just in case a shadow file contains huge values, check for a possible
|
||||||
|
signed integer overflow.
|
||||||
|
|
||||||
|
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
|
||||||
|
Link: <https://github.com/shadow-maint/shadow/pull/876>
|
||||||
|
Signed-off-by: Alejandro Colomar <alx@kernel.org>
|
||||||
|
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/3b5ba41d3e9dfc3bf058f0f31529c08201265241
|
||||||
|
Conflict: src/chpasswd.c
|
||||||
|
---
|
||||||
|
src/passwd.c | 10 ++++------
|
||||||
|
1 file changed, 4 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/passwd.c b/src/passwd.c
|
||||||
|
index 336bbc9..d79767a 100644
|
||||||
|
--- a/src/passwd.c
|
||||||
|
+++ b/src/passwd.c
|
||||||
|
@@ -390,7 +390,6 @@ static int new_password (const struct passwd *pw)
|
||||||
|
*/
|
||||||
|
static void check_password (const struct passwd *pw, const struct spwd *sp)
|
||||||
|
{
|
||||||
|
- time_t now;
|
||||||
|
int exp_status;
|
||||||
|
|
||||||
|
exp_status = isexpired (pw, sp);
|
||||||
|
@@ -410,8 +409,6 @@ static void check_password (const struct passwd *pw, const struct spwd *sp)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) time (&now);
|
||||||
|
-
|
||||||
|
/*
|
||||||
|
* Expired accounts cannot be changed ever. Passwords which are
|
||||||
|
* locked may not be changed. Passwords where min > max may not be
|
||||||
|
@@ -434,10 +431,11 @@ static void check_password (const struct passwd *pw, const struct spwd *sp)
|
||||||
|
* Passwords may only be changed after sp_min time is up.
|
||||||
|
*/
|
||||||
|
if (sp->sp_lstchg > 0) {
|
||||||
|
- time_t ok;
|
||||||
|
- ok = (time_t) sp->sp_lstchg * SCALE;
|
||||||
|
+ long now, ok;
|
||||||
|
+ now = time(NULL) / DAY;
|
||||||
|
+ ok = sp->sp_lstchg;
|
||||||
|
if (sp->sp_min > 0) {
|
||||||
|
- ok += (time_t) sp->sp_min * SCALE;
|
||||||
|
+ ok += sp->sp_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (now < ok) {
|
||||||
|
--
|
||||||
|
2.33.0
|
||||||
|
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
From 23634d8de7d01ed65bd70e316d4da4fe4d9b370d Mon Sep 17 00:00:00 2001
|
||||||
|
From: genBTC <genBTC@gmx.com>
|
||||||
|
Date: Tue, 23 Aug 2022 10:25:51 -0400
|
||||||
|
Subject: [PATCH] useradd: check MLS enablement before setting serange
|
||||||
|
Resolves: https://github.com/shadow-maint/shadow/issues/552
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/23634d8de7d01ed65bd70e316d4da4fe4d9b370d
|
||||||
|
|
||||||
|
---
|
||||||
|
lib/semanage.c | 29 ++++++++++++++++-------------
|
||||||
|
1 file changed, 16 insertions(+), 13 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/lib/semanage.c b/lib/semanage.c
|
||||||
|
index 54f996238..082a6e8ee 100644
|
||||||
|
--- a/lib/semanage.c
|
||||||
|
+++ b/lib/semanage.c
|
||||||
|
@@ -122,12 +122,14 @@ static int semanage_user_mod (semanage_handle_t *handle,
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
|
||||||
|
- if (ret != 0) {
|
||||||
|
- fprintf (shadow_logfd,
|
||||||
|
- _("Could not set serange for %s\n"), login_name);
|
||||||
|
- ret = 1;
|
||||||
|
- goto done;
|
||||||
|
+ if (semanage_mls_enabled(handle)) {
|
||||||
|
+ ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
|
||||||
|
+ if (ret != 0) {
|
||||||
|
+ fprintf (shadow_logfd,
|
||||||
|
+ _("Could not set serange for %s\n"), login_name);
|
||||||
|
+ ret = 1;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = semanage_seuser_set_sename (handle, seuser, seuser_name);
|
||||||
|
@@ -179,13 +181,14 @@ static int semanage_user_add (semanage_handle_t *handle,
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
|
||||||
|
- if (ret != 0) {
|
||||||
|
- fprintf (shadow_logfd,
|
||||||
|
- _("Could not set serange for %s\n"),
|
||||||
|
- login_name);
|
||||||
|
- ret = 1;
|
||||||
|
- goto done;
|
||||||
|
+ if (semanage_mls_enabled(handle)) {
|
||||||
|
+ ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
|
||||||
|
+ if (ret != 0) {
|
||||||
|
+ fprintf (shadow_logfd,
|
||||||
|
+ _("Could not set serange for %s\n"), login_name);
|
||||||
|
+ ret = 1;
|
||||||
|
+ goto done;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = semanage_seuser_set_sename (handle, seuser, seuser_name);
|
||||||
39
backport-useradd-check-if-subid-range-exists-for-user.patch
Normal file
39
backport-useradd-check-if-subid-range-exists-for-user.patch
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
From e0524e813a3bae2891b33a66f35876841c11cee7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
Date: Mon, 24 Oct 2022 10:46:36 +0200
|
||||||
|
Subject: [PATCH] useradd: check if subid range exists for user
|
||||||
|
|
||||||
|
Check if a user already has a subid range before assigning one.
|
||||||
|
|
||||||
|
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2012929
|
||||||
|
|
||||||
|
Signed-off-by: Iker Pedrosa <ipedrosa@redhat.com>
|
||||||
|
|
||||||
|
Conflict: NA
|
||||||
|
Reference: https://github.com/shadow-maint/shadow/commit/f6f8bcd2a57c06983296485cc028ebdf467ebfd7
|
||||||
|
|
||||||
|
---
|
||||||
|
src/useradd.c | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/useradd.c b/src/useradd.c
|
||||||
|
index 7ea0a9c4d..e784d6029 100644
|
||||||
|
--- a/src/useradd.c
|
||||||
|
+++ b/src/useradd.c
|
||||||
|
@@ -2188,14 +2188,14 @@ static void usr_update (unsigned long subuid_count, unsigned long subgid_count)
|
||||||
|
fail_exit (E_PW_UPDATE);
|
||||||
|
}
|
||||||
|
#ifdef ENABLE_SUBIDS
|
||||||
|
- if (is_sub_uid &&
|
||||||
|
+ if (is_sub_uid && !local_sub_uid_assigned(user_name) &&
|
||||||
|
(sub_uid_add(user_name, sub_uid_start, subuid_count) == 0)) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: failed to prepare the new %s entry\n"),
|
||||||
|
Prog, sub_uid_dbname ());
|
||||||
|
fail_exit (E_SUB_UID_UPDATE);
|
||||||
|
}
|
||||||
|
- if (is_sub_gid &&
|
||||||
|
+ if (is_sub_gid && !local_sub_gid_assigned(user_name) &&
|
||||||
|
(sub_gid_add(user_name, sub_gid_start, subgid_count) == 0)) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: failed to prepare the new %s entry\n"),
|
||||||
39
backport-usermod-fix-off-by-one-issues.patch
Normal file
39
backport-usermod-fix-off-by-one-issues.patch
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
From 7a2b302e68a4f3e324b851c7361e40aa20a86a64 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= <cgzones@googlemail.com>
|
||||||
|
Date: Thu, 2 Mar 2023 16:18:45 +0100
|
||||||
|
Subject: [PATCH] usermod: fix off-by-one issues
|
||||||
|
|
||||||
|
Allocate enough memory for the strings, two slashes and the NUL
|
||||||
|
terminator.
|
||||||
|
|
||||||
|
Reported-by: Alejandro Colomar <alx@kernel.org>
|
||||||
|
Signed-off-by: Alejandro Colomar <alx@kernel.org>
|
||||||
|
---
|
||||||
|
src/usermod.c | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/src/usermod.c b/src/usermod.c
|
||||||
|
index 77d4ef49..db5d37a4 100644
|
||||||
|
--- a/src/usermod.c
|
||||||
|
+++ b/src/usermod.c
|
||||||
|
@@ -2048,7 +2048,7 @@ static void move_mailbox (void)
|
||||||
|
if (NULL == maildir) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
- len = strlen (prefix) + strlen (maildir) + strlen (user_name) + 2;
|
||||||
|
+ len = strlen (prefix) + strlen (maildir) + strlen (user_name) + 3;
|
||||||
|
mailfile = alloca (len);
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -2103,7 +2103,7 @@ static void move_mailbox (void)
|
||||||
|
(void) close (fd);
|
||||||
|
|
||||||
|
if (lflg) {
|
||||||
|
- len = strlen (prefix) + strlen (maildir) + strlen (user_newname) + 2;
|
||||||
|
+ len = strlen (prefix) + strlen (maildir) + strlen (user_newname) + 3;
|
||||||
|
newmailfile = alloca(len);
|
||||||
|
if (prefix[0]) {
|
||||||
|
(void) snprintf (newmailfile, len, "%s/%s/%s",
|
||||||
|
--
|
||||||
|
2.27.0
|
||||||
|
|
||||||
26
chpasswd.sh
Normal file
26
chpasswd.sh
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# chpasswd(8) completion -*- shell-script -*-
|
||||||
|
|
||||||
|
_chpasswd()
|
||||||
|
{
|
||||||
|
local cur prev words cword split
|
||||||
|
_init_completion -s || return
|
||||||
|
|
||||||
|
case $prev in
|
||||||
|
-c|--crypt)
|
||||||
|
COMPREPLY=( $( compgen -W 'DES MD5 NONE SHA256 SHA512 SM3' \
|
||||||
|
-- "$cur" ) )
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
-s|--sha-rounds)
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
$split && return
|
||||||
|
|
||||||
|
COMPREPLY=( $( compgen -W '$( _parse_help "$1" )' -- "$cur" ) )
|
||||||
|
[[ $COMPREPLY == *= ]] && compopt -o nospace
|
||||||
|
} &&
|
||||||
|
complete -F _chpasswd chpasswd
|
||||||
|
|
||||||
|
# ex: filetype=sh
|
||||||
133
shadow-Remove-encrypted-passwd-for-useradd-gr.patch
Normal file
133
shadow-Remove-encrypted-passwd-for-useradd-gr.patch
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
From 280a8474ad87f44f9620eeac75cbf8a34b5edc2f Mon Sep 17 00:00:00 2001
|
||||||
|
From: xiongshenglan <xiongshenglan@huawei.com>
|
||||||
|
Date: Thu, 27 Jul 2023 09:30:16 +0800
|
||||||
|
Subject: [PATCH] shadow: Remove encrypted passwd for
|
||||||
|
useradd-groupadd-groupmod-usermod
|
||||||
|
|
||||||
|
Remove encrypted passwd for useradd/groupadd/groupmod/usermod
|
||||||
|
In groupadd/useradd, p parameter does not meet password complexity checks. Do
|
||||||
|
not satisfy security requirements.
|
||||||
|
|
||||||
|
Signed-off-by: xiongshenglan <xiongshenglan@huawei.com>
|
||||||
|
---
|
||||||
|
src/groupadd.c | 4 ++++
|
||||||
|
src/groupmod.c | 4 ++++
|
||||||
|
src/useradd.c | 4 ++++
|
||||||
|
src/usermod.c | 4 ++++
|
||||||
|
4 files changed, 16 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/src/groupadd.c b/src/groupadd.c
|
||||||
|
index d7f68b1..9b7a521 100644
|
||||||
|
--- a/src/groupadd.c
|
||||||
|
+++ b/src/groupadd.c
|
||||||
|
@@ -125,7 +125,9 @@ static /*@noreturn@*/void usage (int status)
|
||||||
|
(void) fputs (_(" -K, --key KEY=VALUE override /etc/login.defs defaults\n"), usageout);
|
||||||
|
(void) fputs (_(" -o, --non-unique allow to create groups with duplicate\n"
|
||||||
|
" (non-unique) GID\n"), usageout);
|
||||||
|
+#ifndef CONFIG_SHADOW_REMOVE_POPTION
|
||||||
|
(void) fputs (_(" -p, --password PASSWORD use this encrypted password for the new group\n"), usageout);
|
||||||
|
+#endif
|
||||||
|
(void) fputs (_(" -r, --system create a system account\n"), usageout);
|
||||||
|
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
|
||||||
|
(void) fputs (_(" -P, --prefix PREFIX_DI directory prefix\n"), usageout);
|
||||||
|
@@ -459,10 +461,12 @@ static void process_flags (int argc, char **argv)
|
||||||
|
case 'o':
|
||||||
|
oflg = true;
|
||||||
|
break;
|
||||||
|
+#ifndef CONFIG_SHADOW_REMOVE_POPTION
|
||||||
|
case 'p':
|
||||||
|
pflg = true;
|
||||||
|
group_passwd = optarg;
|
||||||
|
break;
|
||||||
|
+#endif
|
||||||
|
case 'r':
|
||||||
|
rflg = true;
|
||||||
|
break;
|
||||||
|
diff --git a/src/groupmod.c b/src/groupmod.c
|
||||||
|
index acd6f35..f9dcabd 100644
|
||||||
|
--- a/src/groupmod.c
|
||||||
|
+++ b/src/groupmod.c
|
||||||
|
@@ -139,8 +139,10 @@ static void usage (int status)
|
||||||
|
(void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
|
||||||
|
(void) fputs (_(" -n, --new-name NEW_GROUP change the name to NEW_GROUP\n"), usageout);
|
||||||
|
(void) fputs (_(" -o, --non-unique allow to use a duplicate (non-unique) GID\n"), usageout);
|
||||||
|
+#ifndef CONFIG_SHADOW_REMOVE_POPTION
|
||||||
|
(void) fputs (_(" -p, --password PASSWORD change the password to this (encrypted)\n"
|
||||||
|
" PASSWORD\n"), usageout);
|
||||||
|
+#endif
|
||||||
|
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
|
||||||
|
(void) fputs (_(" -P, --prefix PREFIX_DIR prefix directory where are located the /etc/* files\n"), usageout);
|
||||||
|
(void) fputs (_(" -U, --users USERS list of user members of this group\n"), usageout);
|
||||||
|
@@ -449,10 +451,12 @@ static void process_flags (int argc, char **argv)
|
||||||
|
case 'o':
|
||||||
|
oflg = true;
|
||||||
|
break;
|
||||||
|
+#ifndef CONFIG_SHADOW_REMOVE_POPTION
|
||||||
|
case 'p':
|
||||||
|
group_passwd = optarg;
|
||||||
|
pflg = true;
|
||||||
|
break;
|
||||||
|
+#endif
|
||||||
|
case 'R': /* no-op, handled in process_root_flag () */
|
||||||
|
break;
|
||||||
|
case 'P': /* no-op, handled in process_prefix_flag () */
|
||||||
|
diff --git a/src/useradd.c b/src/useradd.c
|
||||||
|
index 89abd5e..e5ba3dd 100644
|
||||||
|
--- a/src/useradd.c
|
||||||
|
+++ b/src/useradd.c
|
||||||
|
@@ -907,7 +907,9 @@ static void usage (int status)
|
||||||
|
" the user\n"), usageout);
|
||||||
|
(void) fputs (_(" -o, --non-unique allow to create users with duplicate\n"
|
||||||
|
" (non-unique) UID\n"), usageout);
|
||||||
|
+#ifndef CONFIG_SHADOW_REMOVE_POPTION
|
||||||
|
(void) fputs (_(" -p, --password PASSWORD encrypted password of the new account\n"), usageout);
|
||||||
|
+#endif
|
||||||
|
(void) fputs (_(" -r, --system create a system account\n"), usageout);
|
||||||
|
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
|
||||||
|
(void) fputs (_(" -P, --prefix PREFIX_DIR prefix directory where are located the /etc/* files\n"), usageout);
|
||||||
|
@@ -1366,6 +1368,7 @@ static void process_flags (int argc, char **argv)
|
||||||
|
case 'o':
|
||||||
|
oflg = true;
|
||||||
|
break;
|
||||||
|
+#ifndef CONFIG_SHADOW_REMOVE_POPTION
|
||||||
|
case 'p': /* set encrypted password */
|
||||||
|
if (!VALID (optarg)) {
|
||||||
|
fprintf (stderr,
|
||||||
|
@@ -1375,6 +1378,7 @@ static void process_flags (int argc, char **argv)
|
||||||
|
}
|
||||||
|
user_pass = optarg;
|
||||||
|
break;
|
||||||
|
+#endif
|
||||||
|
case 'r':
|
||||||
|
rflg = true;
|
||||||
|
break;
|
||||||
|
diff --git a/src/usermod.c b/src/usermod.c
|
||||||
|
index ca8db92..509a50b 100644
|
||||||
|
--- a/src/usermod.c
|
||||||
|
+++ b/src/usermod.c
|
||||||
|
@@ -435,7 +435,9 @@ static /*@noreturn@*/void usage (int status)
|
||||||
|
(void) fputs (_(" -m, --move-home move contents of the home directory to the\n"
|
||||||
|
" new location (use only with -d)\n"), usageout);
|
||||||
|
(void) fputs (_(" -o, --non-unique allow using duplicate (non-unique) UID\n"), usageout);
|
||||||
|
+#ifndef CONFIG_SHADOW_REMOVE_POPTION
|
||||||
|
(void) fputs (_(" -p, --password PASSWORD use encrypted password for the new password\n"), usageout);
|
||||||
|
+#endif
|
||||||
|
(void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
|
||||||
|
(void) fputs (_(" -P, --prefix PREFIX_DIR prefix directory where are located the /etc/* files\n"), usageout);
|
||||||
|
(void) fputs (_(" -s, --shell SHELL new login shell for the user account\n"), usageout);
|
||||||
|
@@ -1152,10 +1154,12 @@ static void process_flags (int argc, char **argv)
|
||||||
|
case 'o':
|
||||||
|
oflg = true;
|
||||||
|
break;
|
||||||
|
+#ifndef CONFIG_SHADOW_REMOVE_POPTION
|
||||||
|
case 'p':
|
||||||
|
user_pass = optarg;
|
||||||
|
pflg = true;
|
||||||
|
break;
|
||||||
|
+#endif
|
||||||
|
case 'R': /* no-op, handled in process_root_flag () */
|
||||||
|
break;
|
||||||
|
case 'P': /* no-op, handled in process_prefix_flag () */
|
||||||
|
--
|
||||||
|
2.12.3
|
||||||
|
|
||||||
100
shadow.spec
100
shadow.spec
@ -1,6 +1,6 @@
|
|||||||
Name: shadow
|
Name: shadow
|
||||||
Version: 4.9
|
Version: 4.9
|
||||||
Release: 10
|
Release: 15
|
||||||
Epoch: 2
|
Epoch: 2
|
||||||
License: BSD and GPLv2+
|
License: BSD and GPLv2+
|
||||||
Summary: Tools for managing accounts and shadow password files
|
Summary: Tools for managing accounts and shadow password files
|
||||||
@ -12,6 +12,7 @@ Source4: shadow-bsd.txt
|
|||||||
Source5: https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
Source5: https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
||||||
Source6: chpasswd
|
Source6: chpasswd
|
||||||
Source7: newusers
|
Source7: newusers
|
||||||
|
Source8: chpasswd.sh
|
||||||
|
|
||||||
%global includesubiddir %{_includedir}/shadow
|
%global includesubiddir %{_includedir}/shadow
|
||||||
|
|
||||||
@ -37,27 +38,64 @@ Patch17: newgrp-fix-segmentation-fault.patch
|
|||||||
Patch18: groupdel-fix-SIGSEGV-when-passwd-does-not-exist.patch
|
Patch18: groupdel-fix-SIGSEGV-when-passwd-does-not-exist.patch
|
||||||
Patch19: shadow-add-sm3-crypt-support.patch
|
Patch19: shadow-add-sm3-crypt-support.patch
|
||||||
Patch20: backport-useradd-modify-check-ID-range-for-system-users.patch
|
Patch20: backport-useradd-modify-check-ID-range-for-system-users.patch
|
||||||
Patch21: backport-Add-header-guards.patch
|
Patch21: backport-man-po-Makefile.in-switch-from-xml2po-to-itstool.patch
|
||||||
Patch22: backport-Change-to-strncat.patch
|
Patch22: backport-Only-free-sgent-if-it-was-initialized.patch
|
||||||
Patch23: backport-Do-not-return-garbage-in-run_parts.patch
|
Patch23: backport-Fix-parentheses-in-configure.ac.patch
|
||||||
Patch24: backport-Handle-ERANGE-error-correctly.patch
|
Patch24: backport-Added-documentation-around-CREATE_MAIL_SPOOL.patch
|
||||||
Patch25: backport-Initialize-local-variables.patch
|
Patch26: backport-Handle-malformed-lines-in-hushlogins-file.patch
|
||||||
Patch26: backport-Remove-commented-out-code-and-FIXMEs.patch
|
Patch27: backport-Improve-child-error-handling.patch
|
||||||
Patch27: backport-Remove-redeclared-variable.patch
|
Patch28: backport-lib-check-NULL-before-freeing-passwd-data.patch
|
||||||
Patch28: backport-libmisc-add-check-fopen-return-value-in-read_random_.patch
|
Patch29: backport-CVE-2013-4235.patch
|
||||||
Patch29: backport-passwd-erase-password-copy-on-all-error-branches.patch
|
Patch30: backport-Add-header-guards.patch
|
||||||
Patch30: backport-chpasswd-add-get_salt-for-generating-salt-value.patch
|
Patch31: backport-Change-to-strncat.patch
|
||||||
Patch31: backport-chpasswd-fix-function-problem-with-R-parameter.patch
|
Patch32: backport-Handle-ERANGE-error-correctly.patch
|
||||||
Patch32: backport-Fix-off-by-one-mistakes.patch
|
Patch33: backport-Do-not-return-garbage-in-run_parts.patch
|
||||||
Patch33: backport-Fix-typos-in-length-calculations.patch
|
Patch34: backport-Initialize-local-variables.patch
|
||||||
Patch34: backport-Correctly-handle-illegal-system-file-in-tz.patch
|
Patch35: backport-libmisc-add-check-fopen-return-value-in-read_random_.patch
|
||||||
Patch35: backport-Explicitly-override-only-newlines.patch
|
Patch36: backport-passwd-erase-password-copy-on-all-error-branches.patch
|
||||||
Patch36: backport-Prevent-out-of-boundary-access.patch
|
Patch37: backport-Remove-commented-out-code-and-FIXMEs.patch
|
||||||
Patch37: backport-Added-control-character-check.patch
|
Patch38: backport-Remove-redeclared-variable.patch
|
||||||
Patch38: backport-Overhaul-valid_field.patch
|
Patch39: backport-chpasswd-add-get_salt-for-generating-salt-value.patch
|
||||||
Patch39: backport-Read-whole-line-in-yes_or_no.patch
|
Patch40: backport-chpasswd-fix-function-problem-with-R-parameter.patch
|
||||||
Patch40: backport-commonio-free-removed-database-entries.patch
|
Patch41: backport-script-to-kill-subjects-processes-from-userdel.patch
|
||||||
Patch41: backport-semanage-disconnect-to-free-libsemanage-internals.patch
|
Patch42: backport-Avoid-races-in-chown_tree.patch
|
||||||
|
Patch43: backport-Avoid-races-in-remove_tree.patch
|
||||||
|
Patch44: backport-Require-symlink-support.patch
|
||||||
|
Patch45: backport-Fail-if-regular-file-pre-exists-in-copy_tree.patch
|
||||||
|
Patch46: backport-More-robust-file-content-copy-in-copy_tree.patch
|
||||||
|
Patch47: backport-Address-minor-compiler-warnings.patch
|
||||||
|
Patch48: backport-Avoid-races-in-copy_tree.patch
|
||||||
|
Patch49: backport-useradd-check-MLS-enablement-before-setting-serange.patch
|
||||||
|
Patch50: backport-libmisc-minimum-id-check-for-system-accounts.patch
|
||||||
|
Patch51: backort-useradd-Fix-buffer-overflow-when-using-a-prefix.patch
|
||||||
|
Patch52: backport-useradd-check-if-subid-range-exists-for-user.patch
|
||||||
|
Patch53: backport-Fix-off-by-one-mistakes.patch
|
||||||
|
Patch54: backport-Fix-typos-in-length-calculations.patch
|
||||||
|
Patch55: backport-Correctly-handle-illegal-system-file-in-tz.patch
|
||||||
|
Patch56: backport-Explicitly-override-only-newlines.patch
|
||||||
|
Patch57: backport-Prevent-out-of-boundary-access.patch
|
||||||
|
Patch58: backport-Added-control-character-check.patch
|
||||||
|
Patch59: backport-Overhaul-valid_field.patch
|
||||||
|
Patch60: backport-Read-whole-line-in-yes_or_no.patch
|
||||||
|
Patch61: backport-run_parts-for-groupadd-and-groupdel.patch
|
||||||
|
Patch62: backport-commonio-free-removed-database-entries.patch
|
||||||
|
Patch63: backport-semanage-disconnect-to-free-libsemanage-internals.patch
|
||||||
|
Patch64: backport-process_prefix_flag-Drop-privileges.patch
|
||||||
|
Patch65: backport-chsh-Verify-that-login-shell-path-is-absolute.patch
|
||||||
|
Patch66: backport-Plug-econf-memory-leaks.patch
|
||||||
|
Patch67: backport-def_load-avoid-NULL-deref.patch
|
||||||
|
Patch68: backport-Check-if-crypt_method-null-before-dereferencing.patch
|
||||||
|
Patch69: backport-usermod-fix-off-by-one-issues.patch
|
||||||
|
Patch70: backport-gpasswd-1-Fix-password-leak.patch
|
||||||
|
Patch71: backport-chgpasswd-fix-segfault-in-command-line-options.patch
|
||||||
|
Patch72: backport-chpasswd-add-IS_CRYPT_METHOD.patch
|
||||||
|
Patch73: backport-Fix-yescrypt-support.patch
|
||||||
|
Patch74: backport-newgrp-fix-potential-string-injection.patch
|
||||||
|
Patch75: shadow-Remove-encrypted-passwd-for-useradd-gr.patch
|
||||||
|
Patch76: backport-shadow-userdel-add-the-adaptation-to-the-busybox-ps-.patch
|
||||||
|
Patch77: backport-lib-btrfs-avoid-NULL-dereference.patch
|
||||||
|
Patch78: backport-src-passwd.c-Switch-to-day-precision.patch
|
||||||
|
Patch79: backport-src-passwd-add-overflow-check.patch
|
||||||
|
|
||||||
BuildRequires: gcc, libselinux-devel, audit-libs-devel, libsemanage-devel
|
BuildRequires: gcc, libselinux-devel, audit-libs-devel, libsemanage-devel
|
||||||
BuildRequires: libacl-devel, libattr-devel
|
BuildRequires: libacl-devel, libattr-devel
|
||||||
@ -120,6 +158,8 @@ install -p -c -m 0644 %{SOURCE3} $RPM_BUILD_ROOT/%{_sysconfdir}/login.defs
|
|||||||
install -p -c -m 0600 %{SOURCE2} $RPM_BUILD_ROOT/%{_sysconfdir}/default/useradd
|
install -p -c -m 0600 %{SOURCE2} $RPM_BUILD_ROOT/%{_sysconfdir}/default/useradd
|
||||||
install -p -c -m 0644 %{SOURCE6} $RPM_BUILD_ROOT/%{_sysconfdir}/pam.d/chpasswd
|
install -p -c -m 0644 %{SOURCE6} $RPM_BUILD_ROOT/%{_sysconfdir}/pam.d/chpasswd
|
||||||
install -p -c -m 0644 %{SOURCE7} $RPM_BUILD_ROOT/%{_sysconfdir}/pam.d/newusers
|
install -p -c -m 0644 %{SOURCE7} $RPM_BUILD_ROOT/%{_sysconfdir}/pam.d/newusers
|
||||||
|
mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/bash_completion.d
|
||||||
|
install -p -c -m 0644 %{SOURCE8} $RPM_BUILD_ROOT/%{_sysconfdir}/bash_completion.d/chpasswd.sh
|
||||||
|
|
||||||
ln -s useradd $RPM_BUILD_ROOT%{_sbindir}/adduser
|
ln -s useradd $RPM_BUILD_ROOT%{_sbindir}/adduser
|
||||||
ln -s useradd.8 $RPM_BUILD_ROOT/%{_mandir}/man8/adduser.8
|
ln -s useradd.8 $RPM_BUILD_ROOT/%{_mandir}/man8/adduser.8
|
||||||
@ -214,6 +254,7 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la
|
|||||||
%{_sysconfdir}/pam.d/chpasswd
|
%{_sysconfdir}/pam.d/chpasswd
|
||||||
%{_sysconfdir}/pam.d/groupmems
|
%{_sysconfdir}/pam.d/groupmems
|
||||||
%{_sysconfdir}/pam.d/newusers
|
%{_sysconfdir}/pam.d/newusers
|
||||||
|
%{_sysconfdir}/bash_completion.d/chpasswd.sh
|
||||||
|
|
||||||
%files subid-devel
|
%files subid-devel
|
||||||
%{_libdir}/libsubid.so.*
|
%{_libdir}/libsubid.so.*
|
||||||
@ -224,6 +265,21 @@ rm -f $RPM_BUILD_ROOT/%{_libdir}/libsubid.la
|
|||||||
%{_mandir}/*/*
|
%{_mandir}/*/*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Sun Feb 4 2024 zhengxiaoxiao <zhengxiaoxiao2@huawei.com> - 2:4.9-15
|
||||||
|
- backport some patches
|
||||||
|
|
||||||
|
* Thu Nov 9 2023 wangqingsan <wangqingsan@huawei.com> - 2:4.9-14
|
||||||
|
- backport some patches
|
||||||
|
|
||||||
|
* Wed Sep 20 2023 wangyunjia <yunjia.wang@huawei.com> - 2:4.9-13
|
||||||
|
- backport some patches
|
||||||
|
|
||||||
|
* Tue Aug 22 2023 wangyunjia <yunjia.wang@huawei.com> - 2:4.9-12
|
||||||
|
- backport patches from upstream
|
||||||
|
|
||||||
|
* Fri Aug 15 2023 xiongshenglan<xiongshenglan@huawei.com> - 2:4.9-11
|
||||||
|
- Remove encrypted passwd for useradd-groupadd-groupmod-usermod
|
||||||
|
|
||||||
* Mon Jun 19 2023 wangyunjia <yunjia.wang@huawei.com> - 2:4.9-10
|
* Mon Jun 19 2023 wangyunjia <yunjia.wang@huawei.com> - 2:4.9-10
|
||||||
- backport patches from upstream
|
- backport patches from upstream
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user