mirror of
https://git.savannah.gnu.org/git/tar.git
synced 2026-09-20 15:14:14 +00:00
Add SELinux context store/restore/list support.
* gnulib.modules: Add selinux-at. * src/Makefile.am (tar_LDADD): Add LIB_SELINUX. * src/create.c (start_header, dump_file0): Handle selinux contexts. * src/extract.c (delayed_set_stat) <cntx_name>: New member. (delayed_link) <cntx_name>: New member. (set_stat, delay_set_stat) (apply_nonancestor_delayed_set_stat): Handle selinux contexts. * src/tar.c: New options: "--selinux", "--no-selinux". (tar_stat_destroy): Free cntx_name. * src/tar.h (tar_stat_info) <cntx_name>: New member. * src/xattrs.c (xattrs_selinux_get) (xattrs_selinux_set): New functions. (xattrs_print_char): Honor selinux_context_option. (xattrs_print): Print selinux context. * src/xheader.c: Handle new keyword "RHT.security.selinux". * tests/Makefile.am: Add new tests. * tests/testsuite.at: Likewise. * tests/selacl01.at: New test. * tests/selnx01.at: New test.
This commit is contained in:
committed by
Sergey Poznyakoff
parent
d36f5a3cc3
commit
085cace180
+1
-1
@@ -49,4 +49,4 @@ INCLUDES = -I$(top_srcdir)/gnu -I../ -I../gnu -I$(top_srcdir)/lib -I../lib
|
||||
|
||||
LDADD = ../lib/libtar.a ../gnu/libgnu.a $(LIBINTL) $(LIBICONV)
|
||||
|
||||
tar_LDADD = $(LIBS) $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS)
|
||||
tar_LDADD = $(LIBS) $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_EACCESS) $(LIB_SELINUX)
|
||||
|
||||
@@ -953,6 +953,8 @@ start_header (struct tar_stat_info *st)
|
||||
if (st->acls_d_ptr)
|
||||
xheader_store ("SCHILY.acl.default", st, NULL);
|
||||
}
|
||||
if ((selinux_context_option > 0) && st->cntx_name)
|
||||
xheader_store ("RHT.security.selinux", st, NULL);
|
||||
if (xattrs_option > 0)
|
||||
{
|
||||
size_t scan_xattr = 0;
|
||||
@@ -1742,6 +1744,7 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
|
||||
struct stat final_stat;
|
||||
|
||||
xattrs_acls_get (parentfd, name, st, 0, !is_dir);
|
||||
xattrs_selinux_get (parentfd, name, st, fd);
|
||||
xattrs_xattrs_get (parentfd, name, st, fd);
|
||||
|
||||
if (is_dir)
|
||||
@@ -1862,6 +1865,7 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
|
||||
if (NAME_FIELD_SIZE - (archive_format == OLDGNU_FORMAT) < size)
|
||||
write_long_link (st);
|
||||
|
||||
xattrs_selinux_get (parentfd, name, st, 0);
|
||||
xattrs_xattrs_get (parentfd, name, st, 0);
|
||||
|
||||
block_ordinal = current_block_ordinal ();
|
||||
@@ -1885,18 +1889,21 @@ dump_file0 (struct tar_stat_info *st, char const *name, char const *p)
|
||||
{
|
||||
type = CHRTYPE;
|
||||
xattrs_acls_get (parentfd, name, st, 0, true);
|
||||
xattrs_selinux_get (parentfd, name, st, 0);
|
||||
xattrs_xattrs_get (parentfd, name, st, 0);
|
||||
}
|
||||
else if (S_ISBLK (st->stat.st_mode))
|
||||
{
|
||||
type = BLKTYPE;
|
||||
xattrs_acls_get (parentfd, name, st, 0, true);
|
||||
xattrs_selinux_get (parentfd, name, st, 0);
|
||||
xattrs_xattrs_get (parentfd, name, st, 0);
|
||||
}
|
||||
else if (S_ISFIFO (st->stat.st_mode))
|
||||
{
|
||||
type = FIFOTYPE;
|
||||
xattrs_acls_get (parentfd, name, st, 0, true);
|
||||
xattrs_selinux_get (parentfd, name, st, 0);
|
||||
xattrs_xattrs_get (parentfd, name, st, 0);
|
||||
}
|
||||
else if (S_ISSOCK (st->stat.st_mode))
|
||||
|
||||
@@ -100,6 +100,7 @@ struct delayed_set_stat
|
||||
int change_dir;
|
||||
|
||||
/* extended attributes*/
|
||||
char *cntx_name;
|
||||
char *acls_a_ptr;
|
||||
size_t acls_a_len;
|
||||
char *acls_d_ptr;
|
||||
@@ -146,6 +147,9 @@ struct delayed_link
|
||||
hard-linked together. */
|
||||
struct string_list *sources;
|
||||
|
||||
/* SELinux context */
|
||||
char *cntx_name;
|
||||
|
||||
/* ACLs */
|
||||
char *acls_a_ptr;
|
||||
size_t acls_a_len;
|
||||
@@ -386,6 +390,7 @@ set_stat (char const *file_name,
|
||||
causes that linux capabilities becomes cleared. */
|
||||
xattrs_xattrs_set (st, file_name, typeflag, 1);
|
||||
xattrs_acls_set (st, file_name, typeflag);
|
||||
xattrs_selinux_set (st, file_name, typeflag);
|
||||
}
|
||||
|
||||
/* For each entry H in the leading prefix of entries in HEAD that do
|
||||
@@ -457,6 +462,9 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st,
|
||||
data->atflag = atflag;
|
||||
data->after_links = 0;
|
||||
data->change_dir = chdir_current;
|
||||
data->cntx_name = NULL;
|
||||
if (st)
|
||||
assign_string (&data->cntx_name, st->cntx_name);
|
||||
if (st && st->acls_a_ptr)
|
||||
{
|
||||
data->acls_a_ptr = xmemdup (st->acls_a_ptr, st->acls_a_len + 1);
|
||||
@@ -825,6 +833,7 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links)
|
||||
sb.stat.st_gid = data->gid;
|
||||
sb.atime = data->atime;
|
||||
sb.mtime = data->mtime;
|
||||
sb.cntx_name = data->cntx_name;
|
||||
sb.acls_a_ptr = data->acls_a_ptr;
|
||||
sb.acls_a_len = data->acls_a_len;
|
||||
sb.acls_d_ptr = data->acls_d_ptr;
|
||||
@@ -838,6 +847,7 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links)
|
||||
|
||||
delayed_set_stat_head = data->next;
|
||||
xheader_xattr_free (data->xattr_map, data->xattr_map_size);
|
||||
free (data->cntx_name);
|
||||
free (data->acls_a_ptr);
|
||||
free (data->acls_d_ptr);
|
||||
free (data);
|
||||
@@ -1210,6 +1220,8 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made)
|
||||
+ strlen (file_name) + 1);
|
||||
p->sources->next = 0;
|
||||
strcpy (p->sources->string, file_name);
|
||||
p->cntx_name = NULL;
|
||||
assign_string (&p->cntx_name, current_stat_info.cntx_name);
|
||||
p->acls_a_ptr = NULL;
|
||||
p->acls_a_len = 0;
|
||||
p->acls_d_ptr = NULL;
|
||||
@@ -1650,6 +1662,7 @@ apply_delayed_links (void)
|
||||
st1.stat.st_gid = ds->gid;
|
||||
st1.atime = ds->atime;
|
||||
st1.mtime = ds->mtime;
|
||||
st1.cntx_name = ds->cntx_name;
|
||||
st1.acls_a_ptr = ds->acls_a_ptr;
|
||||
st1.acls_a_len = ds->acls_a_len;
|
||||
st1.acls_d_ptr = ds->acls_d_ptr;
|
||||
@@ -1671,6 +1684,7 @@ apply_delayed_links (void)
|
||||
}
|
||||
|
||||
xheader_xattr_free (ds->xattr_map, ds->xattr_map_size);
|
||||
free (ds->cntx_name);
|
||||
|
||||
{
|
||||
struct delayed_link *next = ds->next;
|
||||
|
||||
@@ -304,6 +304,7 @@ enum
|
||||
NO_SAME_OWNER_OPTION,
|
||||
NO_SAME_PERMISSIONS_OPTION,
|
||||
NO_SEEK_OPTION,
|
||||
NO_SELINUX_CONTEXT_OPTION,
|
||||
NO_UNQUOTE_OPTION,
|
||||
NO_WILDCARDS_MATCH_SLASH_OPTION,
|
||||
NO_WILDCARDS_OPTION,
|
||||
@@ -329,6 +330,7 @@ enum
|
||||
RMT_COMMAND_OPTION,
|
||||
RSH_COMMAND_OPTION,
|
||||
SAME_OWNER_OPTION,
|
||||
SELINUX_CONTEXT_OPTION,
|
||||
SHOW_DEFAULTS_OPTION,
|
||||
SHOW_OMITTED_DIRS_OPTION,
|
||||
SHOW_TRANSFORMED_NAMES_OPTION,
|
||||
@@ -549,6 +551,10 @@ static struct argp_option options[] = {
|
||||
N_("specify the include pattern for xattr keys"), GRID+1 },
|
||||
{"xattrs-exclude", XATTR_EXCLUDE, N_("MASK"), 0,
|
||||
N_("specify the exclude pattern for xattr keys"), GRID+1 },
|
||||
{"selinux", SELINUX_CONTEXT_OPTION, 0, 0,
|
||||
N_("Enable the SELinux context support"), GRID+1 },
|
||||
{"no-selinux", NO_SELINUX_CONTEXT_OPTION, 0, 0,
|
||||
N_("Disable the SELinux context support"), GRID+1 },
|
||||
{"acls", ACLS_OPTION, 0, 0,
|
||||
N_("Enable the POSIX ACLs support"), GRID+1 },
|
||||
{"no-acls", NO_ACLS_OPTION, 0, 0,
|
||||
@@ -2184,6 +2190,15 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||
acls_option = -1;
|
||||
break;
|
||||
|
||||
case SELINUX_CONTEXT_OPTION:
|
||||
set_archive_format ("posix");
|
||||
selinux_context_option = 1;
|
||||
break;
|
||||
|
||||
case NO_SELINUX_CONTEXT_OPTION:
|
||||
selinux_context_option = -1;
|
||||
break;
|
||||
|
||||
case XATTR_OPTION:
|
||||
set_archive_format ("posix");
|
||||
xattrs_option = 1;
|
||||
@@ -2585,6 +2600,11 @@ decode_options (int argc, char **argv)
|
||||
&& !READ_LIKE_SUBCOMMAND)
|
||||
USAGE_ERROR ((0, 0, _("--acls can be used only on POSIX archives")));
|
||||
|
||||
if ((selinux_context_option > 0)
|
||||
&& archive_format != POSIX_FORMAT
|
||||
&& !READ_LIKE_SUBCOMMAND)
|
||||
USAGE_ERROR ((0, 0, _("--selinux can be used only on POSIX archives")));
|
||||
|
||||
if ((xattrs_option > 0)
|
||||
&& archive_format != POSIX_FORMAT
|
||||
&& !READ_LIKE_SUBCOMMAND)
|
||||
@@ -2849,6 +2869,7 @@ tar_stat_destroy (struct tar_stat_info *st)
|
||||
free (st->link_name);
|
||||
free (st->uname);
|
||||
free (st->gname);
|
||||
free (st->cntx_name);
|
||||
free (st->acls_a_ptr);
|
||||
free (st->acls_d_ptr);
|
||||
free (st->sparse_map);
|
||||
|
||||
@@ -297,6 +297,8 @@ struct tar_stat_info
|
||||
char *uname; /* user name of owner */
|
||||
char *gname; /* group name of owner */
|
||||
|
||||
char *cntx_name; /* SELinux context for the current archive entry. */
|
||||
|
||||
char *acls_a_ptr; /* Access ACLs for the current archive entry. */
|
||||
size_t acls_a_len; /* Access ACLs for the current archive entry. */
|
||||
|
||||
|
||||
+67
-1
@@ -28,6 +28,7 @@
|
||||
#include "common.h"
|
||||
|
||||
#include "xattr-at.h"
|
||||
#include "selinux-at.h"
|
||||
|
||||
struct xattrs_mask_map
|
||||
{
|
||||
@@ -490,6 +491,64 @@ static void xattrs__fd_set (struct tar_stat_info const *st,
|
||||
}
|
||||
}
|
||||
|
||||
/* lgetfileconat is called against FILE_NAME iff the FD parameter is set to
|
||||
zero, otherwise the fgetfileconat is used against correct file descriptor */
|
||||
void xattrs_selinux_get (int parentfd, char const *file_name,
|
||||
struct tar_stat_info *st, int fd)
|
||||
{
|
||||
if (selinux_context_option > 0)
|
||||
{
|
||||
#if HAVE_SELINUX_SELINUX_H != 1
|
||||
static int done = 0;
|
||||
if (!done)
|
||||
WARN ((0, 0, _("SELinux support is not available")));
|
||||
done = 1;
|
||||
#else
|
||||
int result = (fd ? fgetfilecon (fd, &st->cntx_name)
|
||||
: lgetfileconat (parentfd, file_name, &st->cntx_name));
|
||||
|
||||
if (result == -1 && errno != ENODATA && errno != ENOTSUP)
|
||||
call_arg_warn (fd ? "fgetfilecon" : "lgetfileconat", file_name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void xattrs_selinux_set (struct tar_stat_info const *st,
|
||||
char const *file_name, char typeflag)
|
||||
{
|
||||
if (selinux_context_option > 0)
|
||||
{
|
||||
#if HAVE_SELINUX_SELINUX_H != 1
|
||||
static int done = 0;
|
||||
if (!done)
|
||||
WARN ((0, 0, _("SELinux support is not available")));
|
||||
done = 1;
|
||||
#else
|
||||
const char *sysname = "setfilecon";
|
||||
int ret;
|
||||
|
||||
if (!st->cntx_name)
|
||||
return;
|
||||
|
||||
if (typeflag != SYMTYPE)
|
||||
{
|
||||
ret = setfileconat (chdir_fd, file_name, st->cntx_name);
|
||||
sysname = "setfileconat";
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = lsetfileconat (chdir_fd, file_name, st->cntx_name);
|
||||
sysname = "lsetfileconat";
|
||||
}
|
||||
|
||||
if (ret == -1)
|
||||
WARNOPT (WARN_XATTR_WRITE, (0, errno,
|
||||
_("%s: Cannot set SELinux context for file '%s'"), sysname,
|
||||
file_name));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static bool xattrs_matches_mask (const char *kw, struct xattrs_mask_map *mm)
|
||||
{
|
||||
int i;
|
||||
@@ -589,7 +648,7 @@ void xattrs_print_char (struct tar_stat_info const *st, char *output)
|
||||
return;
|
||||
}
|
||||
|
||||
if (xattrs_option > 0 || acls_option > 0)
|
||||
if (xattrs_option > 0 || selinux_context_option > 0 || acls_option > 0)
|
||||
{
|
||||
/* placeholders */
|
||||
*output = ' ';
|
||||
@@ -606,6 +665,9 @@ void xattrs_print_char (struct tar_stat_info const *st, char *output)
|
||||
break;
|
||||
}
|
||||
|
||||
if (selinux_context_option > 0 && st->cntx_name)
|
||||
*output = '.';
|
||||
|
||||
if (acls_option && (st->acls_a_len || st->acls_d_len))
|
||||
*output = '+';
|
||||
}
|
||||
@@ -615,6 +677,10 @@ void xattrs_print (struct tar_stat_info const *st)
|
||||
if (verbose_option < 3)
|
||||
return;
|
||||
|
||||
/* selinux */
|
||||
if (selinux_context_option && st->cntx_name)
|
||||
fprintf (stdlis, " s: %s\n", st->cntx_name);
|
||||
|
||||
/* acls */
|
||||
if (acls_option && (st->acls_a_len || st->acls_d_len))
|
||||
{
|
||||
|
||||
@@ -469,6 +469,7 @@ void xheader_xattr_init (struct tar_stat_info *st)
|
||||
st->acls_a_len = 0;
|
||||
st->acls_d_ptr = NULL;
|
||||
st->acls_d_len = 0;
|
||||
st->cntx_name = NULL;
|
||||
}
|
||||
|
||||
void xheader_xattr_free (struct xattr_array *xattr_map, size_t xattr_map_size)
|
||||
@@ -1554,6 +1555,20 @@ volume_filename_decoder (struct tar_stat_info *st,
|
||||
decode_string (&continued_file_name, arg);
|
||||
}
|
||||
|
||||
static void
|
||||
xattr_selinux_coder (struct tar_stat_info const *st, char const *keyword,
|
||||
struct xheader *xhdr, void const *data)
|
||||
{
|
||||
code_string (st->cntx_name, keyword, xhdr);
|
||||
}
|
||||
|
||||
static void
|
||||
xattr_selinux_decoder (struct tar_stat_info *st,
|
||||
char const *keyword, char const *arg, size_t size)
|
||||
{
|
||||
decode_string (&st->cntx_name, arg);
|
||||
}
|
||||
|
||||
static void
|
||||
xattr_acls_a_coder (struct tar_stat_info const *st , char const *keyword,
|
||||
struct xheader *xhdr, void const *data)
|
||||
@@ -1703,6 +1718,11 @@ struct xhdr_tab const xhdr_tab[] = {
|
||||
{ "GNU.volume.offset", volume_offset_coder, volume_offset_decoder,
|
||||
XHDR_PROTECTED | XHDR_GLOBAL, false },
|
||||
|
||||
/* We get the SELinux value from filecon, so add a namespace for SELinux
|
||||
instead of storing it in SCHILY.xattr.* (which would be RAW). */
|
||||
{ "RHT.security.selinux",
|
||||
xattr_selinux_coder, xattr_selinux_decoder, 0, false },
|
||||
|
||||
/* ACLs, use the star format... */
|
||||
{ "SCHILY.acl.access",
|
||||
xattr_acls_a_coder, xattr_acls_a_decoder, 0, false },
|
||||
|
||||
Reference in New Issue
Block a user