Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ AC_HEADER_STDBOOL

AC_CHECK_HEADERS(errno.h fcntl.h limits.h unistd.h sys/time.h utmp.h \
utmpx.h termios.h termio.h sgtty.h sys/ioctl.h syslog.h paths.h \
utime.h ulimit.h sys/resource.h gshadow.h lastlog.h \
utime.h ulimit.h sys/capability.h sys/resource.h gshadow.h lastlog.h \
locale.h rpc/key_prot.h netdb.h acl/libacl.h attr/libattr.h \
attr/error_context.h)

Expand Down
45 changes: 44 additions & 1 deletion libmisc/idmapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
#include <stdio.h>
#include "prototypes.h"
#include "idmapping.h"
#include <sys/prctl.h>
#if HAVE_SYS_CAPABILITY_H
# include <sys/capability.h>
#endif

struct map_range *get_map_ranges(int ranges, int argc, char **argv)
{
Expand Down Expand Up @@ -121,17 +125,56 @@ struct map_range *get_map_ranges(int ranges, int argc, char **argv)


void write_mapping(int proc_dir_fd, int ranges, struct map_range *mappings,
const char *map_file)
const char *map_file, uid_t uid)
{
int idx;
struct map_range *mapping;
size_t bufsize;
char *buf, *pos;
int fd;
#if HAVE_SYS_CAPABILITY_H
struct __user_cap_header_struct hdr = { _LINUX_CAPABILITY_VERSION_3, 0 };
struct __user_cap_data_struct data[2] = { { 0 } };
#endif

bufsize = ranges * ((ULONG_DIGITS + 1) * 3);
pos = buf = xmalloc(bufsize);

#if HAVE_SYS_CAPABILITY_H
if (capget(&hdr, data) < 0) {
fprintf(stderr, _("%s: Could not get capabilities\n"), Prog);
exit(EXIT_FAILURE);
}
if (!(data[0].effective & CAP_TO_MASK(CAP_SYS_ADMIN)) &&
uid != geteuid()) {
bool uid_map;

if (strcmp(map_file, "uid_map") == 0) {
uid_map = true;
} else if (strcmp(map_file, "gid_map") == 0) {
uid_map = false;
} else {
fprintf(stderr, _("%s: Invalid map file %s specified\n"), Prog, map_file);
exit(EXIT_FAILURE);
}
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) {
fprintf(stderr, _("%s: Could not prctl(PR_SET_KEEPCAPS)\n"), Prog);
exit(EXIT_FAILURE);
}
if (seteuid(uid) < 0) {
fprintf(stderr, _("%s: Could not seteuid to %d\n"), Prog, uid);
exit(EXIT_FAILURE);
}

memset(data, 0, sizeof(data));
data[0].effective = data[0].permitted = CAP_TO_MASK(uid_map ? CAP_SETUID : CAP_SETGID);
if (capset(&hdr, data) < 0) {
fprintf(stderr, _("%s: Could not set caps\n"), Prog);
exit(EXIT_FAILURE);
}
}
#endif

/* Build the mapping command */
mapping = mappings;
for (idx = 0; idx < ranges; idx++, mapping++) {
Expand Down
2 changes: 1 addition & 1 deletion libmisc/idmapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct map_range {

extern struct map_range *get_map_ranges(int ranges, int argc, char **argv);
extern void write_mapping(int proc_dir_fd, int ranges,
struct map_range *mappings, const char *map_file);
struct map_range *mappings, const char *map_file, uid_t uid);

#endif /* _ID_MAPPING_H_ */

4 changes: 2 additions & 2 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ LIBCRYPT_NOPAM = $(LIBCRYPT)
endif

chage_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBAUDIT) $(LIBSELINUX)
newuidmap_LDADD = $(LDADD) $(LIBSELINUX)
newgidmap_LDADD = $(LDADD) $(LIBSELINUX)
newuidmap_LDADD = $(LDADD) $(LIBSELINUX) $(LIBCAP)
newgidmap_LDADD = $(LDADD) $(LIBSELINUX) $(LIBCAP)
chfn_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD)
chgpasswd_LDADD = $(LDADD) $(LIBPAM_SUID) $(LIBSELINUX) $(LIBCRYPT)
chsh_LDADD = $(LDADD) $(LIBPAM) $(LIBSELINUX) $(LIBCRYPT_NOPAM) $(LIBSKEY) $(LIBMD)
Expand Down
2 changes: 1 addition & 1 deletion src/newgidmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ int main(int argc, char **argv)
verify_ranges(pw, ranges, mappings, &allow_setgroups);

write_setgroups(proc_dir_fd, allow_setgroups);
write_mapping(proc_dir_fd, ranges, mappings, "gid_map");
write_mapping(proc_dir_fd, ranges, mappings, "gid_map", pw->pw_uid);
sub_gid_close();

return EXIT_SUCCESS;
Expand Down
2 changes: 1 addition & 1 deletion src/newuidmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ int main(int argc, char **argv)

verify_ranges(pw, ranges, mappings);

write_mapping(proc_dir_fd, ranges, mappings, "uid_map");
write_mapping(proc_dir_fd, ranges, mappings, "uid_map", pw->pw_uid);
sub_uid_close();

return EXIT_SUCCESS;
Expand Down