Compare commits

...

30 Commits

Author SHA1 Message Date
Jim Meyering
9aee8e78ea * src/runcon.c (main): Don't reorder arguments. Reported by
Ulrich Drepper in <http://bugzilla.redhat.com/232652>.
* tests/misc/runcon-no-reorder: New file.  Test for the above.
* tests/misc/Makefile.am (TESTS): Add runcon-no-reorder.
2007-03-18 18:15:08 +01:00
Jim Meyering
ab511a2106 * src/runcon.c (main): Remove "." at end of a diagnostic. 2007-03-18 18:15:08 +01:00
Jim Meyering
5e711ff948 Arrange for "make check-root" to run the new root-only test.
* tests/Makefile.am (t9): New target, to run tests/cp/cp-a-selinux.
(all_t): Add t9.

Use a directory on a loopback device mounted with -o context=...
* tests/cp/cp-a-selinux: Since this test now runs mount and umount,
it is a root-only one.
2007-03-18 18:15:08 +01:00
Jim Meyering
6f5700ac8a * src/runcon.c: New program.
* src/Makefile.am (bin_PROGRAMS): Add runcon.
(runcon_LDADD): Define.
* README: Add runcon to the list of programs.
* AUTHORS: Add this: runcon: Russell Coker
* tests/help-version: Add runcon as an exception.
* man/Makefile.am (dist_man_MANS): Add runcon.1.
(runcon.1): New dependency.
* po/POTFILES.in: Add src/runcon.c.
2007-03-18 18:15:08 +01:00
Jim Meyering
8daf081cd2 Regenerate .cvsignore and .gitignore files. 2007-03-18 18:15:08 +01:00
Jim Meyering
3f619c59cf mkfifo, mknod: Accept new "-Z, --context=C" option.
* src/mkfifo.c, src/mknod.c: Include <selinux/selinux.h>.
(main): Honor it.
* src/Makefile.am (mkfifo_LDADD, mknod_LDADD): Use $(LIB_SELINUX).
2007-03-18 18:15:08 +01:00
Jim Meyering
0db199df69 mkdir: Accept new "-Z, --context=C" option.
* src/mkdir.c: Include <selinux/selinux.h>.
(main): Honor it.
* src/Makefile.am (mkdir_LDADD): Use $(LIB_SELINUX).
2007-03-18 18:15:08 +01:00
Jim Meyering
beb12e09f3 * tests/cp/cp-a-selinux: New file. Test for the bug reported in
* tests/cp/Makefile.am (TESTS): Add cp-a-selinux.

* tests/selinux: New file.
* tests/Makefile.am (EXTRA_DIST): Add selinux.
* tests/misc/selinux: Source the new script, rather than open coding it.

Change how "cp -a" and "cp --preserve=context" work with SELinux.
Now, cp -a attempts to preserve context, but failure to do so does
not change cp's exit status.  However "cp --preserve=context" is
similar, but failure *does* cause cp to exit with nonzero status.
* src/copy.h (struct cp_options) [require_preserve_context]: New member.
* src/copy.c (copy_reg, copy_internal): Implement the above.
* src/mv.c (cp_option_init): Initialize the new member.
* src/install.c (cp_option_init): Likewise.
* src/cp.c (cp_option_init): Likewise.
(decode_preserve_arg): Set it or reset it.

FIXME: add an on-writable-NFS-only test
2007-03-18 18:15:08 +01:00
Jim Meyering
65ba507e17 * src/system.h (GETOPT_SELINUX_CONTEXT_OPTION_DECL): Define. 2007-03-18 18:15:06 +01:00
Jim Meyering
795c052e33 cp, mv, install: add SELinux support, but unlike with the Red Hat
patch, mv and cp do not provide the "-Z context" option.
* src/copy.c: Include <selinux/selinux.h>.
(restore_default_fscreatecon): New function.
(copy_reg): Make cp --preserve=context work for existing destination.
(copy_internal): Likewise for new destinations.
* src/copy.h (cp_options) [preserve_security_context]: New member.
* src/cp.c: Include <selinux/selinux.h>.
(selinux_enabled): New global.
(usage): Mention new --preserve=context option.
(PRESERVE_CONTEXT): Define/use.
(decode_preserve_arg): Handle PRESERVE_CONTEXT.
(main): Remove an obsolete comment.
If --preserve=context is specified on a system without SELinux
enabled, give a diagnostic and fail.
* src/mv.c: Include <selinux/selinux.h>.
Set x->preserve_security_context if SELinux is enabled.
* src/install.c: Accept new "-Z, --context=C" option.
Accept --preserve-context option (but not -P option).
Accept alternate spelling: --preserve_context, for now.
Include <selinux/selinux.h> and "quotearg.h".
(selinux_enabled, use_default_selinux_context): New globals.
(PRESERVE_CONTEXT_OPTION): Define.
(cp_option_init): Default: do not preserve security context.
(setdefaultfilecon): New function.
(main): Honor new options.
* src/Makefile.am (mv_LDADD, cp_LDADD, ginstall_LDADD):
Add $(LIB_SELINUX).
2007-03-18 18:15:06 +01:00
Jim Meyering
09ef5a443f * tests/misc/selinux [VERBOSE]: Print version info for each
of the tested tools, not just ls.
2007-03-18 18:15:06 +01:00
Jim Meyering
3765e5a26e * src/c99-to-c89.diff: Remove the ls.c patch, now that I've
temporarily removed the offending c99'ism.
2007-03-18 18:15:06 +01:00
Jim Meyering
b64a11dc76 * src/chcon.c (usage): Split a string literal that was longer than 509. 2007-03-18 18:15:06 +01:00
Jim Meyering
82d98da743 * src/ls.c (gobble_file): Don't call getfilecon unless print_scontext.
Upon failed getfilecon, accept not just ENOTSUP, but also ENODATA.
2007-03-18 18:15:06 +01:00
Jim Meyering
ecf70125f9 * src/c99-to-c89.diff: Adjust offsets. 2007-03-18 18:15:06 +01:00
Jim Meyering
1b569150c5 * AUTHORS: Add chcon. 2007-03-18 18:15:05 +01:00
Jim Meyering
4269a52c1a * src/c99-to-c89.diff: Remove trailing blanks. 2007-03-18 18:15:05 +01:00
Jim Meyering
b23de86834 * src/chcon.c: Don't include "dirname.h". system.h already includes it. 2007-03-18 18:15:05 +01:00
Jim Meyering
7782da7bf5 * gl/lib/selinux-at.c: Remove a use of HAVE_CONFIG_H. 2007-03-18 18:15:05 +01:00
Jim Meyering
2b5e4cb837 * src/c99-to-c89.diff: Handle a new c99'ism in ls.c. 2007-03-18 18:15:05 +01:00
Jim Meyering
5f997760c9 * src/id.c (main): Tweak id -Z diagnostic. 2007-03-18 18:15:05 +01:00
Jim Meyering
10ca93af8f * POTFILES.in: Add src/chcon.c. 2007-03-18 18:15:05 +01:00
Jim Meyering
0278a4d7d3 id: Add SELinux support: -Z option.
* src/id.c (main): Apply patches from Fedora, with these changes:
Remove #ifdef WITH_SELINUX.
Use error (EXIT_FAILURE, not fprintf+exit(1).
* src/Makefile.am (id_LDADD): Define, so as to add $(LIB_SELINUX).
2007-03-18 18:15:05 +01:00
Jim Meyering
2aab34d486 Keep SELinux-related ChangLog entries here. 2007-03-18 18:15:05 +01:00
Jim Meyering
2912097e82 stat: Add support for SELinux in the form of a %C format directive.
* src/stat.c (follow_links): Make this variable file-global.
(out_file_context): New function.
(print_statfs): Honor %C.
(print_stat): Honor %C.
(do_stat): Remove follow_links parameter.
(usage): Document the two %C directives.
(main): Accept -Z (though it's a no-op).
* src/Makefile.am (stat_LDADD): Define.
2007-03-18 18:15:05 +01:00
Jim Meyering
3238605998 add chcon 2007-03-18 18:15:05 +01:00
Jim Meyering
1e9098dc83 ls: Add support for SELinux and a slightly modified -Z option.
I started with the patches from Red Hat.
The entries below tell how the code evolved.

* src/ls.c (print_long_format, print_file_name_and_frills): When
there is no security context (due to getfilecon/lgetfilecon failing
with e.g. ENOTSUP), print it as "?", not "".
* src/ls.c (print_file_name_and_frills): Make -Z work without -l.
(length_of_file_name_and_frills): Likewise.

* src/ls.c: Remove the --lcontext and --scontext options.
Change the way -Z, --context work so that it no longer implies -l.
Thus, -Z -l will work like -lcontext and -Z without -l will work
like --scontext.

Adjust tests to reflect new 'ls -l' syntax -- affects only
systems with SELinux when operating on a file with no ACL.
These tests assumed that everything before the first space on
each line is the 10-byte mode string.  But there may also be a "+"
in the 11th column, just before the space.  However, note that this
is not new.  The same thing would have happened even without the
change below, when listing a file with an ACL.
* tests/chmod/equals, tests/cp/cp-parents, tests/cp/fail-perm:
* tests/cp/link-preserve, tests/install/basic-1, tests/misc/mknod:
* tests/mkdir/parents, tests/mkdir/special-1, tests/mv/partition-perm:

Don't make compilation depend on USE_ACL.  An SELinux security
context counts as an "alternate access control method", so ls
must output a "+" for each file with a security context.
* src/ls.c [struct fileinfo] (have_acl): Declare unconditionally.
(FILE_HAS_ACL): Remove macro definition.  Use f->have_acl directly.
(gobble_file): Record whether a file has a security context, and
update the condition used to determine whether to print the "+".
(gobble_file): Call getfilecon/lgetfilecon also when
format == long_format, so that we get the "+".

* src/ls.c (gobble_file): Add a comment explaining why (with a
security context option) ls doesn't exit nonzero due to e.g.,
getfilecon failing with errno == ENOTSUP.

* src/ls.c (gobble_file): Ignore failure of getfilecon if it's due
to ENOTSUP.

* src/ls.c (gobble_file): Factor out three small blocks using
getfilecon and lgetfilecon.
Don't ignore return value from getfilecon and lgetfilecon.

* src/ls.c (print_long_format): Don't use ?: (empty 2nd arg with C
ternary operator).
(print_scontext_format): Likewise.
(print_scontext): Declare to be "bool", not int.  Adjust uses.

* src/Makefile.am (dir_LDADD, ls_LDADD, vdir_LDADD): Add $(LIB_SELINUX).

* tests/misc/chcon: New file.
* tests/misc/chcon-fail: New file.
* tests/Makefile.am (check-root): Run new, root-only misc/chcon test.
* tests/misc/Makefile.am (TESTS): Add chcon and chcon-fail.

* tests/misc/Makefile.am (TESTS): Add selinux.
* tests/misc/selinux: New file.
* tests/help-version: Skip chcon.
2007-03-18 18:15:05 +01:00
Jim Meyering
27940f5d02 * man/chcon.x: New file.
* man/Makefile.am: Build chcon.1.
2007-03-18 18:15:04 +01:00
Jim Meyering
561c3a2b75 .cvsignore, .gitignore: update 2007-03-18 18:15:04 +01:00
Jim Meyering
c1fb4bcb2a New program: chcon
* gl/modules/selinux-at: New module.  Check for libselinux and set
LIB_SELINUX here, unconditionally, rather than depending on
the configure-time --enable-selinux option.
* gl/modules/selinux-h: New module.
* bootstrap.conf (gnulib_modules): Add selinux-at.
* gl/lib/selinux-at.c, gl/lib/selinux-at.h: New files.
* gl/lib/se-selinux_.h: New file.
* gl/lib/se-context_.h: New file.
* gl/m4/selinux-selinux-h.m4: New file.
* gl/m4/selinux-context-h.m4: New file.
* src/Makefile.am (bin_PROGRAMS): Add chcon.
(chcon_LDADD): Define.
* README: Add chcon to the list of programs.
* src/chcon.c: Rewrite the original (Red Hat) chcon to use fts.
2007-03-18 18:15:04 +01:00
58 changed files with 2297 additions and 108 deletions

View File

@@ -8,6 +8,7 @@ Makefile
Makefile.in
THANKS-to-translators
aclocal.m4
chcon
config.status
configure
coreutils-*

1
.gitignore vendored
View File

@@ -13,6 +13,7 @@ Makefile.in
THANKS-to-translators
aclocal.m4
autom4te.cache
chcon
config.cache
config.h
config.hin

View File

@@ -4,6 +4,7 @@ each followed by the name(s) of its author(s).
base64: Simon Josefsson
basename: FIXME unknown
cat: Torbjorn Granlund, Richard M. Stallman
chcon: Russell Coker, Jim Meyering
chgrp: David MacKenzie, Jim Meyering
chmod: David MacKenzie, Jim Meyering
chown: David MacKenzie, Jim Meyering
@@ -60,6 +61,7 @@ pwd: Jim Meyering
readlink: Dmitry V. Levin
rm: Paul Rubin, David MacKenzie, Richard Stallman, Jim Meyering
rmdir: David MacKenzie
runcon: Russell Coker
seq: Ulrich Drepper
sha1sum: Ulrich Drepper, Scott Miller, David Madore
sha224sum: Ulrich Drepper, Scott Miller, David Madore

View File

@@ -486,9 +486,17 @@
consistent, so this can be applied with patch -p0.
Reported by Matthew Woehlke.
Arrange for "make check-root" to run the new root-only test.
* tests/Makefile.am (t9): New target, to run tests/cp/cp-a-selinux.
(all_t): Add t9.
* Makefile.maint (patch-check): Use patch with its -p2 option,
since that makes this check slightly more strict.
Use a directory on a loopback device mounted with -o context=...
* tests/cp/cp-a-selinux: Since this test now runs mount and umount,
it is a root-only one.
2007-01-29 Jim Meyering <jim@meyering.net>
Plug a leak in ls.

208
ChangeLog-selinux Normal file
View File

@@ -0,0 +1,208 @@
2007-03-18 Jim Meyering <jim@meyering.net>
* src/runcon.c (main): Don't reorder arguments. Reported by
Ulrich Drepper in <http://bugzilla.redhat.com/232652>.
* tests/misc/runcon-no-reorder: New file. Test for the above.
* tests/misc/Makefile.am (TESTS): Add runcon-no-reorder.
* src/runcon.c (main): Remove "." at end of a diagnostic.
2007-02-02 Jim Meyering <jim@meyering.net>
* src/runcon.c: New program.
* src/Makefile.am (bin_PROGRAMS): Add runcon.
(runcon_LDADD): Define.
* README: Add runcon to the list of programs.
* AUTHORS: Add this: runcon: Russell Coker
* tests/help-version: Add runcon as an exception.
* man/Makefile.am (dist_man_MANS): Add runcon.1.
(runcon.1): New dependency.
2007-01-31 Jim Meyering <jim@meyering.net>
mkfifo, mknod: Accept new "-Z, --context=C" option.
* src/mkfifo.c, src/mknod.c: Include <selinux/selinux.h>.
(main): Honor it.
* src/Makefile.am (mkfifo_LDADD, mknod_LDADD): Use $(LIB_SELINUX).
mkdir: Accept new "-Z, --context=C" option.
* src/mkdir.c: Include <selinux/selinux.h>.
(main): Honor it.
* src/Makefile.am (mkdir_LDADD): Use $(LIB_SELINUX).
* tests/cp/cp-a-selinux: New file. Test for the bug reported in
<http://bugzilla.redhat.com/219900>.
* tests/cp/Makefile.am (TESTS): Add cp-a-selinux.
* tests/selinux: New file.
* tests/Makefile.am (EXTRA_DIST): Add selinux.
* tests/misc/selinux: Source the new script, rather than open coding it.
Change how "cp -a" and "cp --preserve=context" work with SELinux.
Now, cp -a attempts to preserve context, but failure to do so does
not change cp's exit status. However "cp --preserve=context" is
similar, but failure *does* cause cp to exit with nonzero status.
* src/copy.h (struct cp_options) [require_preserve_context]: New member.
* src/copy.c (copy_reg, copy_internal): Implement the above.
* src/mv.c (cp_option_init): Initialize the new member.
* src/install.c (cp_option_init): Likewise.
* src/cp.c (cp_option_init): Likewise.
(decode_preserve_arg): Set it or reset it.
FIXME: add an on-writable-NFS-only test
2007-01-20 Jim Meyering <jim@meyering.net>
cp, mv, install: add SELinux support, but unlike with the Red Hat
patch, mv and cp do not provide the "-Z context" option.
* src/copy.c: Include <selinux/selinux.h>.
(restore_default_fscreatecon): New function.
(copy_reg): Make cp --preserve=context work for existing destination.
(copy_internal): Likewise for new destinations.
* src/copy.h (cp_options) [preserve_security_context]: New member.
* src/cp.c: Include <selinux/selinux.h>.
(selinux_enabled): New global.
(usage): Mention new --preserve=context option.
(PRESERVE_CONTEXT): Define/use.
(decode_preserve_arg): Handle PRESERVE_CONTEXT.
(main): Remove an obsolete comment.
If --preserve=context is specified on a system without SELinux
enabled, give a diagnostic and fail.
* src/mv.c: Include <selinux/selinux.h>.
Set x->preserve_security_context if SELinux is enabled.
* src/install.c: Accept new "-Z, --context=C" option.
Accept --preserve-context option (but not -P option).
Accept alternate spelling: --preserve_context, for now.
Include <selinux/selinux.h> and "quotearg.h".
(selinux_enabled, use_default_selinux_context): New globals.
(PRESERVE_CONTEXT_OPTION): Define.
(cp_option_init): Default: do not preserve security context.
(setdefaultfilecon): New function.
(main): Honor new options.
* src/Makefile.am (mv_LDADD, cp_LDADD, ginstall_LDADD):
Add $(LIB_SELINUX).
* src/system.h (GETOPT_SELINUX_CONTEXT_OPTION_DECL): Define.
* tests/misc/selinux [VERBOSE]: Print version info for each
of the tested tools, not just ls.
* src/c99-to-c89.diff: Remove the ls.c patch, now that I've
temporarily removed the offending c99'ism.
* src/chcon.c (usage): Split a string literal that was longer than 509.
* src/ls.c (gobble_file): Don't call getfilecon unless print_scontext.
Upon failed getfilecon, accept not just ENOTSUP, but also ENODATA.
* src/c99-to-c89.diff: Adjust offsets.
* AUTHORS: Add chcon.
* src/c99-to-c89.diff: Remove trailing blanks.
* src/chcon.c: Don't include "dirname.h". system.h already includes it.
* gl/lib/selinux-at.c: Remove a use of HAVE_CONFIG_H.
* src/c99-to-c89.diff: Handle a new c99'ism in ls.c.
* src/id.c (main): Tweak id -Z diagnostic.
id: Add SELinux support: -Z option.
* src/id.c (main): Apply patches from Fedora, with these changes:
Remove #ifdef WITH_SELINUX.
Use error (EXIT_FAILURE, not fprintf+exit(1).
* src/Makefile.am (id_LDADD): Define, so as to add $(LIB_SELINUX).
2007-01-06 Jim Meyering <jim@meyering.net>
stat: Add support for SELinux in the form of a %C format directive.
* src/stat.c (follow_links): Make this variable file-global.
(out_file_context): New function.
(print_statfs): Honor %C.
(print_stat): Honor %C.
(do_stat): Remove follow_links parameter.
(usage): Document the two %C directives.
(main): Accept -Z (though it's a no-op).
* src/Makefile.am (stat_LDADD): Define.
ls: Add support for SELinux and a slightly modified -Z option.
I started with the patches from Red Hat.
The entries below tell how the code evolved.
* src/ls.c (print_long_format, print_file_name_and_frills): When
there is no security context (due to getfilecon/lgetfilecon failing
with e.g. ENOTSUP), print it as "?", not "".
* src/ls.c (print_file_name_and_frills): Make -Z work without -l.
(length_of_file_name_and_frills): Likewise.
* src/ls.c: Remove the --lcontext and --scontext options.
Change the way -Z, --context work so that it no longer implies -l.
Thus, -Z -l will work like -lcontext and -Z without -l will work
like --scontext.
Adjust tests to reflect new 'ls -l' syntax -- affects only
systems with SELinux when operating on a file with no ACL.
These tests assumed that everything before the first space on
each line is the 10-byte mode string. But there may also be a "+"
in the 11th column, just before the space. However, note that this
is not new. The same thing would have happened even without the
change below, when listing a file with an ACL.
* tests/chmod/equals, tests/cp/cp-parents, tests/cp/fail-perm:
* tests/cp/link-preserve, tests/install/basic-1, tests/misc/mknod:
* tests/mkdir/parents, tests/mkdir/special-1, tests/mv/partition-perm:
Don't make compilation depend on USE_ACL. An SELinux security
context counts as an "alternate access control method", so ls
must output a "+" for each file with a security context.
* src/ls.c [struct fileinfo] (have_acl): Declare unconditionally.
(FILE_HAS_ACL): Remove macro definition. Use f->have_acl directly.
(gobble_file): Record whether a file has a security context, and
update the condition used to determine whether to print the "+".
(gobble_file): Call getfilecon/lgetfilecon also when
format == long_format, so that we get the "+".
* src/ls.c (gobble_file): Add a comment explaining why (with a
security context option) ls doesn't exit nonzero due to e.g.,
getfilecon failing with errno == ENOTSUP.
* src/ls.c (gobble_file): Ignore failure of getfilecon if it's due
to ENOTSUP.
* src/ls.c (gobble_file): Factor out three small blocks using
getfilecon and lgetfilecon.
Don't ignore return value from getfilecon and lgetfilecon.
* src/ls.c (print_long_format): Don't use ?: (empty 2nd arg with C
ternary operator).
(print_scontext_format): Likewise.
(print_scontext): Declare to be "bool", not int. Adjust uses.
* src/Makefile.am (dir_LDADD, ls_LDADD, vdir_LDADD): Add $(LIB_SELINUX).
* tests/misc/chcon: New file.
* tests/misc/chcon-fail: New file.
* tests/Makefile.am (check-root): Run new, root-only misc/chcon test.
* tests/misc/Makefile.am (TESTS): Add chcon and chcon-fail.
* tests/misc/Makefile.am (TESTS): Add selinux.
* tests/misc/selinux: New file.
* tests/help-version: Skip chcon.
* man/chcon.x: New file.
* man/Makefile.am: Build chcon.1.
New program: chcon
* gl/modules/selinux-at: New module. Check for libselinux and set
LIB_SELINUX here, unconditionally, rather than depending on
the configure-time --enable-selinux option.
* gl/modules/selinux-h: New module.
* bootstrap.conf (gnulib_modules): Add selinux-at.
* gl/lib/selinux-at.c, gl/lib/selinux-at.h: New files.
* gl/lib/se-selinux_.h: New file.
* gl/lib/se-context_.h: New file.
* gl/m4/selinux-selinux-h.m4: New file.
* gl/m4/selinux-context-h.m4: New file.
* src/Makefile.am (bin_PROGRAMS): Add chcon.
(chcon_LDADD): Define.
* README: Add chcon to the list of programs.
* src/chcon.c: Rewrite the original (Red Hat) chcon to use fts.

16
README
View File

@@ -7,14 +7,14 @@ arbitrary limits.
The programs that can be built with this package are:
[ base64 basename cat chgrp chmod chown chroot cksum comm cp csplit cut date
dd df dir dircolors dirname du echo env expand expr factor false fmt fold
ginstall groups head hostid hostname id join kill link ln logname ls
md5sum mkdir mkfifo mknod mv nice nl nohup od paste pathchk pinky pr
printenv printf ptx pwd readlink rm rmdir seq sha1sum sha224sum sha256sum
sha384sum sha512sum shred shuf sleep sort split stat stty su sum sync tac
tail tee test touch tr true tsort tty uname unexpand uniq unlink uptime
users vdir wc who whoami yes
[ base64 basename cat chcon chgrp chmod chown chroot cksum comm cp
csplit cut date dd df dir dircolors dirname du echo env expand expr
factor false fmt fold ginstall groups head hostid hostname id join
kill link ln logname ls md5sum mkdir mkfifo mknod mv nice nl nohup
od paste pathchk pinky pr printenv printf ptx pwd readlink rm rmdir
runcon seq sha1sum sha224sum sha256sum sha384sum sha512sum shred shuf
sleep sort split stat stty su sum sync tac tail tee test touch tr true
tsort tty uname unexpand uniq unlink uptime users vdir wc who whoami yes
See the file NEWS for a list of major changes in the current release.

View File

@@ -60,7 +60,9 @@ gnulib_modules="
root-dev-ino
rpmatch
safe-read same
save-cwd savedir savewd settime sha1 sig2str ssize_t stat-macros
save-cwd savedir savewd
selinux-at
settime sha1 sig2str ssize_t stat-macros
stat-time stdbool stdlib-safer stpcpy strftime
strpbrk strtoimax strtoumax strverscmp sys_stat timespec tzset
unicodeio unistd-safer unlink-busy unlinkdir unlocked-io

31
gl/lib/se-context_.h Normal file
View File

@@ -0,0 +1,31 @@
#ifndef SELINUX_CONTEXT_H
# define SELINUX_CONTEXT_H
# include <errno.h>
/* Some systems don't have ENOSYS. */
# ifndef ENOSYS
# ifdef ENOTSUP
# define ENOSYS ENOTSUP
# else
/* Some systems don't have ENOTSUP either. */
# define ENOSYS EINVAL
# endif
# endif
typedef int context_t;
static inline context_t context_new (char const *s)
{ errno = ENOTSUP; return 0; }
static inline char *context_str (context_t con)
{ errno = ENOTSUP; return (void *) 0; }
static inline void context_free (context_t c) {}
static inline int context_user_set (context_t sc, char const *s)
{ errno = ENOTSUP; return -1; }
static inline int context_role_set (context_t sc, char const *s)
{ errno = ENOTSUP; return -1; }
static inline int context_range_set (context_t sc, char const *s)
{ errno = ENOTSUP; return -1; }
static inline int context_type_set (context_t sc, char const *s)
{ errno = ENOTSUP; return -1; }
#endif

54
gl/lib/se-selinux_.h Normal file
View File

@@ -0,0 +1,54 @@
#ifndef SELINUX_SELINUX_H
# define SELINUX_SELINUX_H
# include <sys/types.h>
# include <errno.h>
/* Some systems don't have ENOSYS. */
# ifndef ENOSYS
# ifdef ENOTSUP
# define ENOSYS ENOTSUP
# else
/* Some systems don't have ENOTSUP either. */
# define ENOSYS EINVAL
# endif
# endif
typedef unsigned short security_class_t;
# define security_context_t char*
# define is_selinux_enabled() 0
static inline int getcon (security_context_t *con) { errno = ENOTSUP; return -1; }
static inline void freecon (security_context_t con) {}
static inline int getfscreatecon (security_context_t *con)
{ errno = ENOTSUP; return -1; }
static inline int setfscreatecon (security_context_t con)
{ errno = ENOTSUP; return -1; }
static inline int matchpathcon (char const *s, mode_t m,
security_context_t *con)
{ errno = ENOTSUP; return -1; }
static inline int getfilecon (char const *s, security_context_t *con)
{ errno = ENOTSUP; return -1; }
static inline int lgetfilecon (char const *s, security_context_t *con)
{ errno = ENOTSUP; return -1; }
static inline int setfilecon (char const *s, security_context_t con)
{ errno = ENOTSUP; return -1; }
static inline int lsetfilecon (char const *s, security_context_t con)
{ errno = ENOTSUP; return -1; }
static inline int fsetfilecon (int fd, security_context_t con)
{ errno = ENOTSUP; return -1; }
static inline int security_check_context (security_context_t con)
{ errno = ENOTSUP; return -1; }
static inline int security_check_context_raw (security_context_t con)
{ errno = ENOTSUP; return -1; }
static inline int setexeccon (security_context_t con)
{ errno = ENOTSUP; return -1; }
static inline int security_compute_create (security_context_t scon,
security_context_t tcon,
security_class_t tclass,
security_context_t *newcon)
{ errno = ENOTSUP; return -1; }
#endif

92
gl/lib/selinux-at.c Normal file
View File

@@ -0,0 +1,92 @@
/* openat-style fd-relative functions for SE Linux
Copyright (C) 2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* written by Jim Meyering */
#include <config.h>
#include "selinux-at.h"
#include "openat.h"
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */
#include "save-cwd.h"
#include "gettext.h"
#define _(msgid) gettext (msgid)
#include "openat-priv.h"
#define AT_FUNC_NAME getfileconat
#define AT_FUNC_F1 getfilecon
#define AT_FUNC_F2 getfilecon
#define AT_FUNC_USE_F1_COND 1
#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t *con
#define AT_FUNC_POST_FILE_ARGS , con
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
#undef AT_FUNC_F2
#undef AT_FUNC_USE_F1_COND
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS
#define AT_FUNC_NAME lgetfileconat
#define AT_FUNC_F1 lgetfilecon
#define AT_FUNC_F2 lgetfilecon
#define AT_FUNC_USE_F1_COND 1
#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t *con
#define AT_FUNC_POST_FILE_ARGS , con
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
#undef AT_FUNC_F2
#undef AT_FUNC_USE_F1_COND
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS
#define AT_FUNC_NAME setfileconat
#define AT_FUNC_F1 setfilecon
#define AT_FUNC_F2 setfilecon
#define AT_FUNC_USE_F1_COND 1
#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t con
#define AT_FUNC_POST_FILE_ARGS , con
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
#undef AT_FUNC_F2
#undef AT_FUNC_USE_F1_COND
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS
#define AT_FUNC_NAME lsetfileconat
#define AT_FUNC_F1 lsetfilecon
#define AT_FUNC_F2 lsetfilecon
#define AT_FUNC_USE_F1_COND 1
#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t con
#define AT_FUNC_POST_FILE_ARGS , con
#include "at-func.c"
#undef AT_FUNC_NAME
#undef AT_FUNC_F1
#undef AT_FUNC_F2
#undef AT_FUNC_USE_F1_COND
#undef AT_FUNC_POST_FILE_PARAM_DECLS
#undef AT_FUNC_POST_FILE_ARGS

24
gl/lib/selinux-at.h Normal file
View File

@@ -0,0 +1,24 @@
/* Prototypes for openat-style fd-relative SELinux functions
Copyright (C) 2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include <selinux/selinux.h>
#include <selinux/context.h>
int getfileconat (int fd, char const *file, security_context_t *con);
int lgetfileconat (int fd, char const *file, security_context_t *con);
int setfileconat (int fd, char const *file, security_context_t con);
int lsetfileconat (int fd, char const *file, security_context_t con);

View File

@@ -0,0 +1,18 @@
# serial 1 -*- Autoconf -*-
# Copyright (C) 2006 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# From Jim Meyering
# Provide <selinux/context.h>, if necessary.
AC_DEFUN([gl_HEADERS_SELINUX_CONTEXT_H],
[
AC_LIBSOURCES([se-context_.h])
# Check for <selinux/context.h>,
AC_CHECK_HEADERS([selinux/context.h],
[SELINUX_CONTEXT_H=],
[SELINUX_CONTEXT_H=selinux/context.h])
AC_SUBST([SELINUX_CONTEXT_H])
])

View File

@@ -0,0 +1,18 @@
# serial 1 -*- Autoconf -*-
# Copyright (C) 2006 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# From Jim Meyering
# Provide <selinux/selinux.h>, if necessary.
AC_DEFUN([gl_HEADERS_SELINUX_SELINUX_H],
[
AC_LIBSOURCES([se-selinux_.h])
# Check for <selinux/selinux.h>,
AC_CHECK_HEADERS([selinux/selinux.h],
[SELINUX_SELINUX_H=],
[SELINUX_SELINUX_H=selinux/selinux.h])
AC_SUBST([SELINUX_SELINUX_H])
])

32
gl/modules/selinux-at Normal file
View File

@@ -0,0 +1,32 @@
Description:
openat-style fd-relative functions for SE Linux
Files:
lib/selinux-at.c
lib/selinux-at.h
Depends-on:
selinux-h
configure.ac:
# FIXME: put this in an .m4 file?
# For runcon.
AC_CHECK_HEADERS([selinux/flask.h])
AC_LIBOBJ([selinux-at])
ac_save_LIBS="$LIBS"
AC_SEARCH_LIBS(setfilecon, selinux,
[test "$ac_cv_search_setfilecon" = "none required" ||
LIB_SELINUX=$ac_cv_search_setfilecon])
AC_SUBST(LIB_SELINUX)
LIBS="$ac_save_LIBS"
Makefile.am:
Include:
selinux-at.h
License:
LGPL
Maintainer:
Jim Meyering

54
gl/modules/selinux-h Normal file
View File

@@ -0,0 +1,54 @@
Description:
SELinux-related headers for systems that lack them.
Files:
lib/se-context_.h
lib/se-selinux_.h
m4/selinux-context-h.m4
m4/selinux-selinux-h.m4
Depends-on:
configure.ac:
gl_HEADERS_SELINUX_SELINUX_H
gl_HEADERS_SELINUX_CONTEXT_H
Makefile.am:
BUILT_SOURCES += $(SELINUX_SELINUX_H)
selinux/selinux.h: se-selinux_.h
mkdir -p selinux
cp $(srcdir)/se-selinux_.h $@-t
chmod a-x $@-t
mv $@-t $@
MOSTLYCLEANFILES += selinux/selinux.h selinux/selinux.h-t
BUILT_SOURCES += $(SELINUX_CONTEXT_H)
selinux/context.h: se-context_.h
mkdir -p selinux
cp $(srcdir)/se-context_.h $@-t
chmod a-x $@-t
mv $@-t $@
MOSTLYCLEANFILES += selinux/context.h selinux/context.h-t
MOSTLYCLEANDIRS += selinux
Include:
#include <selinux/selinux.h>
#include <selinux/context.h>
License:
LGPL
Maintainer:
Jim Meyering
# lib/selinux-at.c
#
# # For runcon.
# AC_CHECK_HEADERS([selinux/flask.h])
#
# ac_save_LIBS="$LIBS"
# AC_SEARCH_LIBS(setfilecon, selinux,
# [test "$ac_cv_search_setfilecon" = "none required" ||
# LIB_SELINUX=$ac_cv_search_setfilecon])
# AC_SUBST(LIB_SELINUX)
# LIBS="$ac_save_LIBS"

View File

@@ -286,7 +286,14 @@ savedir.c
savedir.h
savewd.c
savewd.h
se-context.h
se-context_.h
se-selinux.h
se-selinux_.h
search.h
selinux
selinux-at.c
selinux-at.h
setenv.c
setenv.h
settime.c

7
lib/.gitignore vendored
View File

@@ -279,6 +279,13 @@ savedir.c
savedir.h
savewd.c
savewd.h
se-context.h
se-context_.h
se-selinux.h
se-selinux_.h
selinux
selinux-at.c
selinux-at.h
setenv.c
setenv.h
settime.c

View File

@@ -175,6 +175,8 @@ same.m4
save-cwd.m4
savedir.m4
savewd.m4
selinux-context-h.m4
selinux-selinux-h.m4
setenv.m4
settime.m4
sha1.m4

2
m4/.gitignore vendored
View File

@@ -168,6 +168,8 @@ same.m4
save-cwd.m4
savedir.m4
savewd.m4
selinux-context-h.m4
selinux-selinux-h.m4
setenv.m4
settime.m4
sha1.m4

View File

@@ -18,14 +18,15 @@
# 02110-1301, USA.
dist_man_MANS = \
base64.1 basename.1 cat.1 chgrp.1 chmod.1 chown.1 cksum.1 comm.1 \
base64.1 basename.1 cat.1 chcon.1 chgrp.1 chmod.1 chown.1 cksum.1 comm.1 \
cp.1 csplit.1 cut.1 date.1 dd.1 df.1 dir.1 dircolors.1 dirname.1 du.1 \
echo.1 env.1 expand.1 expr.1 factor.1 false.1 fmt.1 fold.1 groups.1 \
head.1 hostname.1 id.1 install.1 join.1 kill.1 \
link.1 ln.1 logname.1 \
ls.1 md5sum.1 mkdir.1 mkfifo.1 mknod.1 mv.1 nl.1 nohup.1 od.1 \
paste.1 pathchk.1 pr.1 printenv.1 printf.1 ptx.1 pwd.1 readlink.1 \
rm.1 rmdir.1 seq.1 sha1sum.1 sha224sum.1 sha256sum.1 sha384sum.1 sha512sum.1 \
rm.1 rmdir.1 runcon.1 seq.1 \
sha1sum.1 sha224sum.1 sha256sum.1 sha384sum.1 sha512sum.1 \
shred.1 shuf.1 sleep.1 sort.1 split.1 stat.1 \
su.1 sum.1 sync.1 tac.1 tail.1 tee.1 test.1 touch.1 tr.1 true.1 tsort.1 \
tty.1 unexpand.1 uniq.1 unlink.1 vdir.1 wc.1 \
@@ -45,6 +46,7 @@ common_dep = $(top_srcdir)/configure.ac
base64.1: $(common_dep) $(srcdir)/base64.x ../src/base64.c
basename.1: $(common_dep) $(srcdir)/basename.x ../src/basename.c
cat.1: $(common_dep) $(srcdir)/cat.x ../src/cat.c
chcon.1: $(common_dep) $(srcdir)/chcon.x ../src/chcon.c
chgrp.1: $(common_dep) $(srcdir)/chgrp.x ../src/chgrp.c
chmod.1: $(common_dep) $(srcdir)/chmod.x ../src/chmod.c
chown.1: $(common_dep) $(srcdir)/chown.x ../src/chown.c
@@ -104,6 +106,7 @@ pwd.1: $(common_dep) $(srcdir)/pwd.x ../src/pwd.c
readlink.1: $(common_dep) $(srcdir)/readlink.x ../src/readlink.c
rm.1: $(common_dep) $(srcdir)/rm.x ../src/rm.c
rmdir.1: $(common_dep) $(srcdir)/rmdir.x ../src/rmdir.c
runcon.1: $(common_dep) $(srcdir)/runcon.x ../src/runcon.c
seq.1: $(common_dep) $(srcdir)/seq.x ../src/seq.c
sha1sum.1: $(common_dep) $(srcdir)/sha1sum.x ../src/md5sum.c
sha224sum.1: $(common_dep) $(srcdir)/sha224sum.x ../src/md5sum.c

4
man/chcon.x Normal file
View File

@@ -0,0 +1,4 @@
[NAME]
chcon \- change file security context
[DESCRIPTION]
.\" Add any additional description here

14
man/runcon.x Normal file
View File

@@ -0,0 +1,14 @@
[NAME]
runcon \- run command with specified security context
[DESCRIPTION]
Run COMMAND with completely-specified CONTEXT, or with current or
transitioned security context modified by one or more of LEVEL,
ROLE, TYPE, and USER.
.PP
If none of \fI-c\fR, \fI-t\fR, \fI-u\fR, \fI-r\fR, or \fI-l\fR, is specified,
the first argument is used as the complete context. Any additional
arguments after \fICOMMAND\fR are interpreted as arguments to the
command.
.PP
Note that only carefully-chosen contexts are likely to successfully
run.

View File

@@ -1,3 +1,11 @@
2007-02-02 Jim Meyering <jim@meyering.net>
* POTFILES.in: Add src/runcon.c.
2007-01-13 Jim Meyering <jim@meyering.net>
* POTFILES.in: Add src/chcon.c.
2006-10-19 Jim Meyering <jim@meyering.net>
* POTFILES.in: Also include lib/regcomp.c, since it too uses gettext.

View File

@@ -1,5 +1,5 @@
# List of files which contain translatable strings.
# Copyright (C) 1996-2006 Free Software Foundation, Inc.
# Copyright (C) 1996-2007 Free Software Foundation, Inc.
# These are nominally temporary...
lib/acl.c
@@ -33,6 +33,7 @@ lib/xstrtol.h
src/base64.c
src/basename.c
src/cat.c
src/chcon.c
src/chgrp.c
src/chmod.c
src/chown-core.c
@@ -90,6 +91,7 @@ src/readlink.c
src/remove.c
src/rm.c
src/rmdir.c
src/runcon.c
src/seq.c
src/setuidgid.c
src/shred.c

View File

@@ -19,14 +19,15 @@
EXTRA_PROGRAMS = chroot df hostid nice pinky stty su uname uptime users who
bin_SCRIPTS = groups
bin_PROGRAMS = [ chgrp chown chmod cp dd dircolors du \
bin_PROGRAMS = [ chcon chgrp chown chmod cp dd dircolors du \
ginstall link ln dir vdir ls mkdir \
mkfifo mknod mv nohup readlink rm rmdir shred stat sync touch unlink \
cat cksum comm csplit cut expand fmt fold head join md5sum \
nl od paste pr ptx sha1sum sha224sum sha256sum sha384sum sha512sum \
shuf sort split sum tac tail tr tsort unexpand uniq wc \
basename date dirname echo env expr factor false \
hostname id kill logname pathchk printenv printf pwd seq sleep tee \
hostname id kill logname pathchk printenv printf pwd \
runcon seq sleep tee \
test true tty whoami yes \
base64 \
$(OPTIONAL_BIN_PROGS) $(DF_PROG)
@@ -60,9 +61,14 @@ AM_CPPFLAGS = -I$(top_srcdir)/lib
LDADD = ../lib/libcoreutils.a $(LIBINTL) ../lib/libcoreutils.a
# for eaccess in lib/euidaccess.c.
cp_LDADD = $(LDADD) $(LIB_EACCESS)
ginstall_LDADD = $(LDADD) $(LIB_EACCESS)
mv_LDADD = $(LDADD) $(LIB_EACCESS)
chcon_LDADD = $(LDADD) $(LIB_SELINUX)
cp_LDADD = $(LDADD) $(LIB_EACCESS) $(LIB_SELINUX)
ginstall_LDADD = $(LDADD) $(LIB_EACCESS) $(LIB_SELINUX)
mkdir_LDADD = $(LDADD) $(LIB_SELINUX)
mkfifo_LDADD = $(LDADD) $(LIB_SELINUX)
mknod_LDADD = $(LDADD) $(LIB_SELINUX)
mv_LDADD = $(LDADD) $(LIB_EACCESS) $(LIB_SELINUX)
runcon_LDADD = $(LDADD) $(LIB_SELINUX)
pathchk_LDADD = $(LDADD) $(LIB_EACCESS)
rm_LDADD = $(LDADD) $(LIB_EACCESS)
test_LDADD = $(LDADD) $(LIB_EACCESS)
@@ -71,12 +77,13 @@ __LDADD = $(LDADD) $(LIB_EACCESS)
# for clock_gettime and fdatasync
dd_LDADD = $(LDADD) $(LIB_GETHRXTIME) $(LIB_FDATASYNC)
dir_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
ls_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
dir_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_SELINUX)
id_LDADD = $(LDADD) $(LIB_SELINUX)
ls_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_SELINUX)
pr_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
shred_LDADD = $(LDADD) $(LIB_GETHRXTIME) $(LIB_FDATASYNC)
shuf_LDADD = $(LDADD) $(LIB_GETHRXTIME)
vdir_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
vdir_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_SELINUX)
## If necessary, add -lm to resolve use of pow in lib/strtod.c.
sort_LDADD = $(LDADD) $(POW_LIB) $(LIB_GETHRXTIME)
@@ -111,6 +118,8 @@ cp_LDADD += $(LIB_ACL)
mv_LDADD += $(LIB_ACL)
ginstall_LDADD += $(LIB_ACL)
stat_LDADD = $(LDADD) $(LIB_SELINUX)
$(PROGRAMS): ../lib/libcoreutils.a
SUFFIXES = .sh

590
src/chcon.c Normal file
View File

@@ -0,0 +1,590 @@
/* chcon -- change security context of files
Copyright (C) 2005-2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#include <getopt.h>
#include "system.h"
#include "dev-ino.h"
#include "error.h"
#include "openat.h"
#include "quote.h"
#include "quotearg.h"
#include "root-dev-ino.h"
#include "selinux-at.h"
#include "xfts.h"
/* The official name of this program (e.g., no `g' prefix). */
#define PROGRAM_NAME "chcon"
#define AUTHORS "Russell Coker", "Jim Meyering"
enum Change_status
{
CH_NOT_APPLIED,
CH_SUCCEEDED,
CH_FAILED,
CH_NO_CHANGE_REQUESTED
};
enum Verbosity
{
/* Print a message for each file that is processed. */
V_high,
/* Print a message for each file whose attributes we change. */
V_changes_only,
/* Do not be verbose. This is the default. */
V_off
};
/* The name the program was run with. */
char *program_name;
/* If nonzero, and the systems has support for it, change the context
of symbolic links rather than any files they point to. */
static bool affect_symlink_referent;
/* If true, change the modes of directories recursively. */
static bool recurse;
/* Level of verbosity. */
static bool verbose;
/* Pointer to the device and inode numbers of `/', when --recursive.
Otherwise NULL. */
static struct dev_ino *root_dev_ino;
/* The name of the context file is being given. */
static char const *specified_context;
/* Specific components of the context */
static char const *specified_user;
static char const *specified_role;
static char const *specified_range;
static char const *specified_type;
/* For long options that have no equivalent short option, use a
non-character as a pseudo short option, starting with CHAR_MAX + 1. */
enum
{
DEREFERENCE_OPTION = CHAR_MAX + 1,
NO_PRESERVE_ROOT,
PRESERVE_ROOT,
REFERENCE_FILE_OPTION
};
static struct option const long_options[] =
{
{"recursive", no_argument, NULL, 'R'},
{"dereference", no_argument, NULL, DEREFERENCE_OPTION},
{"no-dereference", no_argument, NULL, 'h'},
{"no-preserve-root", no_argument, NULL, NO_PRESERVE_ROOT},
{"preserve-root", no_argument, NULL, PRESERVE_ROOT},
{"reference", required_argument, NULL, REFERENCE_FILE_OPTION},
{"user", required_argument, NULL, 'u'},
{"role", required_argument, NULL, 'r'},
{"type", required_argument, NULL, 't'},
{"range", required_argument, NULL, 'l'},
{"verbose", no_argument, NULL, 'v'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
};
/* Given a security context, CONTEXT, derive a context_t (*RET),
setting any portions selected via the global variables, specified_user,
specified_role, etc. */
static int
compute_context_from_mask (security_context_t context, context_t *ret)
{
bool ok = true;
context_t new_context = context_new (context);
if (!new_context)
{
error (0, errno, _("failed to create security context: %s"),
quotearg_colon (context));
return 1;
}
#define SET_COMPONENT(C, comp) \
do \
{ \
if (specified_ ## comp \
&& context_ ## comp ## _set ((C), specified_ ## comp)) \
{ \
error (0, errno, \
_("failed to set %s security context component to %s"), \
#comp, quote (specified_ ## comp)); \
ok = false; \
} \
} \
while (0)
SET_COMPONENT (new_context, user);
SET_COMPONENT (new_context, range);
SET_COMPONENT (new_context, role);
SET_COMPONENT (new_context, type);
if (!ok)
{
int saved_errno = errno;
context_free (new_context);
errno = saved_errno;
return 1;
}
*ret = new_context;
return 0;
}
/* Change the context of FILE, using specified components.
If it is a directory and -R is given, recurse.
Return 0 if successful, 1 if errors occurred. */
static int
change_file_context (int fd, char const *file)
{
security_context_t file_context = NULL;
context_t context;
security_context_t context_string;
int errors = 0;
if (specified_context == NULL)
{
int status = (affect_symlink_referent
? getfileconat (fd, file, &file_context)
: lgetfileconat (fd, file, &file_context));
if (status < 0 && errno != ENODATA)
{
error (0, errno, _("failed to get security context of %s"),
quote (file));
return 1;
}
/* If the file doesn't have a context, and we're not setting all of
the context components, there isn't really an obvious default.
Thus, we just give up. */
if (file_context == NULL)
{
error (0, 0, _("can't apply partial context to unlabeled file %s"),
quote (file));
return 1;
}
if (compute_context_from_mask (file_context, &context))
return 1;
}
else
{
/* FIXME: this should be done exactly once, in main. */
context = context_new (specified_context);
if (!context)
abort ();
}
context_string = context_str (context);
if (file_context == NULL || ! STREQ (context_string, file_context))
{
int fail = (affect_symlink_referent
? setfileconat (fd, file, context_string)
: lsetfileconat (fd, file, context_string));
if (fail)
{
errors = 1;
error (0, errno, _("failed to change context of %s to %s"),
quote_n (0, file), quote_n (1, context_string));
}
}
context_free (context);
freecon (file_context);
return errors;
}
/* Change the context of FILE.
Return true if successful. This function is called
once for every file system object that fts encounters. */
static bool
process_file (FTS *fts, FTSENT *ent)
{
char const *file_full_name = ent->fts_path;
char const *file = ent->fts_accpath;
const struct stat *file_stats = ent->fts_statp;
bool ok = true;
switch (ent->fts_info)
{
case FTS_D:
if (recurse)
{
if (ROOT_DEV_INO_CHECK (root_dev_ino, ent->fts_statp))
{
/* This happens e.g., with "chcon -R --preserve-root ... /"
and with "chcon -RH --preserve-root ... symlink-to-root". */
ROOT_DEV_INO_WARN (file_full_name);
/* Tell fts not to traverse into this hierarchy. */
fts_set (fts, ent, FTS_SKIP);
/* Ensure that we do not process "/" on the second visit. */
ent = fts_read (fts);
return false;
}
return true;
}
break;
case FTS_DP:
if (! recurse)
return true;
break;
case FTS_NS:
/* For a top-level file or directory, this FTS_NS (stat failed)
indicator is determined at the time of the initial fts_open call.
With programs like chmod, chown, and chgrp, that modify
permissions, it is possible that the file in question is
accessible when control reaches this point. So, if this is
the first time we've seen the FTS_NS for this file, tell
fts_read to stat it "again". */
if (ent->fts_level == 0 && ent->fts_number == 0)
{
ent->fts_number = 1;
fts_set (fts, ent, FTS_AGAIN);
return true;
}
error (0, ent->fts_errno, _("cannot access %s"), quote (file_full_name));
ok = false;
break;
case FTS_ERR:
error (0, ent->fts_errno, _("%s"), quote (file_full_name));
ok = false;
break;
case FTS_DNR:
error (0, ent->fts_errno, _("cannot read directory %s"),
quote (file_full_name));
ok = false;
break;
default:
break;
}
if (ent->fts_info == FTS_DP
&& ok && ROOT_DEV_INO_CHECK (root_dev_ino, file_stats))
{
ROOT_DEV_INO_WARN (file_full_name);
ok = false;
}
if (ok)
{
if (verbose)
printf (_("changing security context of %s"),
quote (file_full_name));
if (change_file_context (fts->fts_cwd_fd, file) != 0)
ok = false;
}
if ( ! recurse)
fts_set (fts, ent, FTS_SKIP);
return ok;
}
/* Recursively operate on the specified FILES (the last entry
of which is NULL). BIT_FLAGS controls how fts works.
Return true if successful. */
static bool
process_files (char **files, int bit_flags)
{
bool ok = true;
FTS *fts = xfts_open (files, bit_flags, NULL);
while (1)
{
FTSENT *ent;
ent = fts_read (fts);
if (ent == NULL)
{
if (errno != 0)
{
/* FIXME: try to give a better message */
error (0, errno, _("fts_read failed"));
ok = false;
}
break;
}
ok &= process_file (fts, ent);
}
/* Ignore failure, since the only way it can do so is in failing to
return to the original directory, and since we're about to exit,
that doesn't matter. */
fts_close (fts);
return ok;
}
void
usage (int status)
{
if (status != EXIT_SUCCESS)
fprintf (stderr, _("Try `%s --help' for more information.\n"),
program_name);
else
{
printf (_("\
Usage: %s [OPTION]... CONTEXT FILE...\n\
or: %s [OPTION]... [-u USER] [-r ROLE] [-l RANGE] [-t TYPE] FILE...\n\
or: %s [OPTION]... --reference=RFILE FILE...\n\
"),
program_name, program_name, program_name);
fputs (_("\
Change the security context of each FILE to CONTEXT.\n\
With --reference, change the security context of each FILE to that of RFILE.\n\
\n\
-c, --changes like verbose but report only when a change is made\n\
-h, --no-dereference affect symbolic links instead of any referenced file\n\
(available only on systems with lchown system call)\n\
"), stdout);
fputs (_("\
--reference=RFILE use RFILE's security context rather than specifying\n\
a CONTEXT value\n\
-R, --recursive operate on files and directories recursively\n\
-v, --verbose output a diagnostic for every file processed\n\
"), stdout);
fputs (_("\
-u, --user=USER set user USER in the target security context\n\
-r, --role=ROLE set role ROLE in the target security context\n\
-t, --type=TYPE set type TYPE in the target security context\n\
-l, --range=RANGE set range RANGE in the target security context\n\
\n\
"), stdout);
fputs (_("\
The following options modify how a hierarchy is traversed when the -R\n\
option is also specified. If more than one is specified, only the final\n\
one takes effect.\n\
\n\
-H if a command line argument is a symbolic link\n\
to a directory, traverse it\n\
-L traverse every symbolic link to a directory\n\
encountered\n\
-P do not traverse any symbolic links (default)\n\
\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
}
exit (status);
}
int
main (int argc, char **argv)
{
security_context_t ref_context = NULL;
/* Bit flags that control how fts works. */
int bit_flags = FTS_PHYSICAL;
/* 1 if --dereference, 0 if --no-dereference, -1 if neither has been
specified. */
int dereference = -1;
bool ok;
bool preserve_root = false;
bool component_specified = false;
char *reference_file = NULL;
int optc;
initialize_main (&argc, &argv);
program_name = argv[0];
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
atexit (close_stdout);
while ((optc = getopt_long (argc, argv, "HLPRchvu:r:t:l:", long_options, NULL))
!= -1)
{
switch (optc)
{
case 'H': /* Traverse command-line symlinks-to-directories. */
bit_flags = FTS_COMFOLLOW | FTS_PHYSICAL;
break;
case 'L': /* Traverse all symlinks-to-directories. */
bit_flags = FTS_LOGICAL;
break;
case 'P': /* Traverse no symlinks-to-directories. */
bit_flags = FTS_PHYSICAL;
break;
case 'h': /* --no-dereference: affect symlinks */
dereference = 0;
break;
case DEREFERENCE_OPTION: /* --dereference: affect the referent
of each symlink */
dereference = 1;
break;
case NO_PRESERVE_ROOT:
preserve_root = false;
break;
case PRESERVE_ROOT:
preserve_root = true;
break;
case REFERENCE_FILE_OPTION:
reference_file = optarg;
break;
case 'R':
recurse = true;
break;
case 'f':
/* ignore */
break;
case 'v':
verbose = true;
break;
case 'u':
specified_user = optarg;
component_specified = true;
break;
case 'r':
specified_role = optarg;
component_specified = true;
break;
case 't':
specified_type = optarg;
component_specified = true;
break;
case 'l':
specified_range = optarg;
component_specified = true;
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
usage (EXIT_FAILURE);
}
}
if (recurse)
{
if (bit_flags == FTS_PHYSICAL)
{
if (dereference == 1)
error (EXIT_FAILURE, 0,
_("-R --dereference requires either -H or -L"));
affect_symlink_referent = false;
}
else
{
if (dereference == 0)
error (EXIT_FAILURE, 0, _("-R -h requires -P"));
affect_symlink_referent = true;
}
}
else
{
bit_flags = FTS_PHYSICAL;
affect_symlink_referent = (dereference != 0);
}
if (argc - optind < (reference_file || component_specified ? 1 : 2))
{
if (argc <= optind)
error (0, 0, _("missing operand"));
else
error (0, 0, _("missing operand after %s"), quote (argv[argc - 1]));
usage (EXIT_FAILURE);
}
if (reference_file)
{
if (getfilecon (reference_file, &ref_context) < 0)
error (EXIT_FAILURE, errno, _("failed to get security context of %s"),
quote (reference_file));
specified_context = ref_context;
}
else if (component_specified)
{
/* FIXME: it's already null, so this is a no-op. */
specified_context = NULL;
}
else
{
context_t context;
specified_context = argv[optind++];
context = context_new (specified_context);
if (!context)
error (EXIT_FAILURE, 0, _("invalid context: %s"),
quotearg_colon (specified_context));
context_free (context);
}
if (reference_file && component_specified)
{
error (0, 0, _("conflicting security context specifiers given"));
usage (1);
}
if (recurse & preserve_root)
{
static struct dev_ino dev_ino_buf;
root_dev_ino = get_root_dev_ino (&dev_ino_buf);
if (root_dev_ino == NULL)
error (EXIT_FAILURE, errno, _("failed to get attributes of %s"),
quote ("/"));
}
else
{
root_dev_ino = NULL;
}
ok = process_files (argv + optind, bit_flags | FTS_NOSTAT);
exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
}

View File

@@ -21,6 +21,7 @@
#include <stdio.h>
#include <assert.h>
#include <sys/types.h>
#include <selinux/selinux.h>
#if HAVE_HURD_H
# include <hurd.h>
@@ -302,6 +303,42 @@ copy_reg (char const *src_name, char const *dst_name,
{
dest_desc = open (dst_name, O_WRONLY | O_TRUNC | O_BINARY);
/* When using cp --preserve=context to copy to an existing destination,
use the default context rather than that of the source. Why?
1) the src context may prohibit writing, and
2) because it's more consistent to use the same context
that is used when the destination file doesn't already exist. */
if (x->preserve_security_context && 0 <= dest_desc)
{
security_context_t con;
if (getfscreatecon (&con) < 0)
{
error (0, errno, _("failed to get file system create context"));
if (x->require_preserve_context)
{
return_val = false;
goto close_src_desc;
}
}
if (con)
{
if (fsetfilecon (dest_desc, con) < 0)
{
error (0, errno,
_("failed to set the security context of %s to %s"),
quote_n (0, dst_name), quote_n (1, con));
if (x->require_preserve_context)
{
return_val = false;
freecon (con);
goto close_src_desc;
}
}
freecon(con);
}
}
if (dest_desc < 0 && x->unlink_dest_after_failed_open)
{
if (unlink (dst_name) != 0)
@@ -995,6 +1032,15 @@ emit_verbose (char const *src, char const *dst, char const *backup_dst_name)
putchar ('\n');
}
/* A wrapper around "setfscreatecon (NULL)" that exits upon failure. */
static void
restore_default_fscreatecon_or_die (void)
{
if (setfscreatecon (NULL) != 0)
error (EXIT_FAILURE, errno,
_("failed to restore the default file creation context"));
}
/* Copy the file SRC_NAME to the file DST_NAME. The files may be of
any type. NEW_DST should be true if the file DST_NAME cannot
exist because its parent directory was just created; NEW_DST should
@@ -1343,7 +1389,7 @@ copy_internal (char const *src_name, char const *dst_name,
if (x->move_mode && src_sb.st_nlink == 1)
{
earlier_file = src_to_dest_lookup (src_sb.st_ino, src_sb.st_dev);
earlier_file = src_to_dest_lookup (src_sb.st_ino, src_sb.st_dev);
}
else if ((x->preserve_links
&& (1 < src_sb.st_nlink
@@ -1533,6 +1579,38 @@ copy_internal (char const *src_name, char const *dst_name,
delayed_ok = true;
if (x->preserve_security_context)
{
security_context_t con;
if (0 <= lgetfilecon (src_name, &con))
{
if (setfscreatecon (con) < 0)
{
error (0, errno,
_("failed to set default file creation context to %s"),
quote (con));
if (x->require_preserve_context)
{
freecon (con);
return false;
}
}
freecon (con);
}
else
{
if (errno != ENOTSUP && errno != ENODATA)
{
error (0, errno,
_("failed to get security context of %s"),
quote (src_name));
if (x->require_preserve_context)
return false;
}
}
}
/* In certain modes (cp's --symbolic-link), and for certain file types
(symlinks and hard links) it doesn't make sense to preserve metadata,
or it's possible to preserve only some of it.
@@ -1762,6 +1840,9 @@ copy_internal (char const *src_name, char const *dst_name,
}
}
if (x->preserve_security_context)
restore_default_fscreatecon_or_die ();
/* There's no need to preserve timestamps or permissions. */
preserve_metadata = false;
@@ -1895,6 +1976,9 @@ copy_internal (char const *src_name, char const *dst_name,
un_backup:
if (x->preserve_security_context)
restore_default_fscreatecon_or_die ();
/* We have failed to create the destination file.
If we've just added a dev/ino entry via the remember_copied
call above (i.e., unless we've just failed to create a hard link),

View File

@@ -1,5 +1,5 @@
/* core functions for copying files and directories
Copyright (C) 89, 90, 91, 1995-2005 Free Software Foundation.
Copyright (C) 89, 90, 91, 1995-2007 Free Software Foundation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -142,10 +142,25 @@ struct cp_options
/* If true and any of the above (for preserve) file attributes cannot
be applied to a destination file, treat it as a failure and return
nonzero immediately. E.g. cp -p requires this be nonzero, mv requires
it be zero. */
nonzero immediately. E.g. for cp -p this must be true, for mv it
must be false. */
bool require_preserve;
/* If true, attempt to preserve the SELinux security context, too.
Set this only if the kernel is SELinux enabled. */
bool preserve_security_context;
/* Useful only when preserve_security_context is true.
If true, a failed attempt to preserve a file's security context
propagates failure "out" to the caller. If false, a failure to
preserve a file's security context does not change the invoking
application's exit status. Give diagnostics for failed syscalls
regardless of this setting. For example, with "cp --preserve=context"
this flag is "true", while with "cp -a", it is false. That means
"cp -a" attempts to preserve any security context, but does not
fail if it is unable to do so. */
bool require_preserve_context;
/* If true, copy directories recursively and copy special files
as themselves rather than copying their contents. */
bool recursive;

View File

@@ -21,6 +21,7 @@
#include <stdio.h>
#include <sys/types.h>
#include <getopt.h>
#include <selinux/selinux.h>
#include "system.h"
#include "argmatch.h"
@@ -85,6 +86,9 @@ enum
/* The invocation name of this program. */
char *program_name;
/* True if the kernel is SELinux enabled. */
static bool selinux_enabled;
/* If true, the command "cp x/e_file e_dir" uses "e_dir/x/e_file"
as its destination instead of the usual "e_dir/e_file." */
static bool parents_option = false;
@@ -191,7 +195,7 @@ Mandatory arguments to long options are mandatory for short options too.\n\
-p same as --preserve=mode,ownership,timestamps\n\
--preserve[=ATTR_LIST] preserve the specified attributes (default:\n\
mode,ownership,timestamps), if possible\n\
additional attributes: links, all\n\
additional attributes: context, links, all\n\
"), stdout);
fputs (_("\
--no-preserve=ATTR_LIST don't preserve the specified attributes\n\
@@ -749,6 +753,8 @@ cp_option_init (struct cp_options *x)
x->preserve_links = false;
x->preserve_mode = false;
x->preserve_timestamps = false;
x->preserve_security_context = false;
x->require_preserve_context = false;
x->require_preserve = false;
x->recursive = false;
@@ -777,18 +783,19 @@ decode_preserve_arg (char const *arg, struct cp_options *x, bool on_off)
PRESERVE_TIMESTAMPS,
PRESERVE_OWNERSHIP,
PRESERVE_LINK,
PRESERVE_CONTEXT,
PRESERVE_ALL
};
static enum File_attribute const preserve_vals[] =
{
PRESERVE_MODE, PRESERVE_TIMESTAMPS,
PRESERVE_OWNERSHIP, PRESERVE_LINK, PRESERVE_ALL
PRESERVE_OWNERSHIP, PRESERVE_LINK, PRESERVE_CONTEXT, PRESERVE_ALL
};
/* Valid arguments to the `--preserve' option. */
static char const* const preserve_args[] =
{
"mode", "timestamps",
"ownership", "links", "all", NULL
"ownership", "links", "context", "all", NULL
};
ARGMATCH_VERIFY (preserve_args, preserve_vals);
@@ -824,11 +831,18 @@ decode_preserve_arg (char const *arg, struct cp_options *x, bool on_off)
x->preserve_links = on_off;
break;
case PRESERVE_CONTEXT:
x->preserve_security_context = on_off;
x->require_preserve_context = on_off;
break;
case PRESERVE_ALL:
x->preserve_mode = on_off;
x->preserve_timestamps = on_off;
x->preserve_ownership = on_off;
x->preserve_links = on_off;
if (selinux_enabled)
x->preserve_security_context = on_off;
break;
default:
@@ -862,6 +876,7 @@ main (int argc, char **argv)
atexit (close_stdout);
selinux_enabled = (0 < is_selinux_enabled ());
cp_option_init (&x);
/* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
@@ -1048,9 +1063,6 @@ main (int argc, char **argv)
x.dereference = DEREF_ALWAYS;
}
/* The key difference between -d (--no-dereference) and not is the version
of `stat' to call. */
if (x.recursive)
x.copy_as_regular = copy_contents;
@@ -1059,6 +1071,14 @@ main (int argc, char **argv)
if (x.unlink_dest_after_failed_open & (x.hard_link | x.symbolic_link))
x.unlink_dest_before_opening = true;
if (x.preserve_security_context)
{
if (!selinux_enabled)
error (EXIT_FAILURE, 0,
_("cannot preserve security context "
"without an SELinux-enabled kernel"));
}
/* Allocate space for remembering copied and created files. */
hash_init ();

View File

@@ -1,5 +1,5 @@
/* id -- print real and effective UIDs and GIDs
Copyright (C) 1989-2005 Free Software Foundation, Inc.
Copyright (C) 1989-2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@
#include <pwd.h>
#include <grp.h>
#include <getopt.h>
#include <selinux/selinux.h>
#include "system.h"
#include "error.h"
@@ -37,6 +38,9 @@
int getugroups ();
/* If nonzero, output only the SELinux context. -Z */
static int just_context = 0;
static void print_user (uid_t uid);
static void print_group (gid_t gid);
static void print_group_list (const char *username);
@@ -55,8 +59,13 @@ static gid_t rgid, egid;
/* True unless errors have been encountered. */
static bool ok = true;
/* The SELinux context. Start with a known invalid value so print_full_info
knows when `context' has not been set to a meaningful value. */
static security_context_t context = NULL;
static struct option const longopts[] =
{
{"context", no_argument, NULL, 'Z'},
{"group", no_argument, NULL, 'g'},
{"groups", no_argument, NULL, 'G'},
{"name", no_argument, NULL, 'n'},
@@ -80,6 +89,7 @@ usage (int status)
Print information for USERNAME, or the current user.\n\
\n\
-a ignore, for compatibility with other versions\n\
-Z, --context print only the security context of the current user\n\
-g, --group print only the effective group ID\n\
-G, --groups print all group IDs\n\
-n, --name print a name instead of a number, for -ugG\n\
@@ -101,6 +111,7 @@ int
main (int argc, char **argv)
{
int optc;
int selinux_enabled = (is_selinux_enabled () > 0);
/* If true, output the list of all group IDs. -G */
bool just_group_list = false;
@@ -119,13 +130,22 @@ main (int argc, char **argv)
atexit (close_stdout);
while ((optc = getopt_long (argc, argv, "agnruG", longopts, NULL)) != -1)
while ((optc = getopt_long (argc, argv, "agnruGZ", longopts, NULL)) != -1)
{
switch (optc)
{
case 'a':
/* Ignore -a, for compatibility with SVR4. */
break;
case 'Z':
/* politely decline if we're not on a selinux-enabled kernel. */
if (!selinux_enabled)
error (EXIT_FAILURE, 0,
_("--context (-Z) works only on an SELinux-enabled kernel"));
just_context = 1;
break;
case 'g':
just_group = true;
break;
@@ -148,19 +168,38 @@ main (int argc, char **argv)
}
}
if (just_user + just_group + just_group_list > 1)
error (EXIT_FAILURE, 0, _("cannot print only user and only group"));
if (just_user + just_group + just_group_list == 0 && (use_real | use_name))
error (EXIT_FAILURE, 0,
_("cannot print only names or real IDs in default format"));
if (argc - optind > 1)
if (1 < argc - optind)
{
error (0, 0, _("extra operand %s"), quote (argv[optind + 1]));
usage (EXIT_FAILURE);
}
if (argc - optind == 1 && just_context)
error (EXIT_FAILURE, 0,
_("cannot print security context when user specified"));
if (just_context && !selinux_enabled)
error (EXIT_FAILURE, 0, _("\
cannot display context when selinux not enabled or when displaying the id\n\
of a different user"));
/* If we are on a selinux-enabled kernel, get our context.
Otherwise, leave the context variable alone - it has
been initialized known invalid value; if we see this invalid
value later, we will know we are on a non-selinux kernel. */
if (selinux_enabled)
{
if (getcon (&context) && just_context)
error (EXIT_FAILURE, 0, _("can't get process context"));
}
if (just_user + just_group + just_group_list + just_context > 1)
error (EXIT_FAILURE, 0, _("cannot print \"only\" of more than one choice"));
if (just_user + just_group + just_group_list == 0 && (use_real | use_name))
error (EXIT_FAILURE, 0,
_("cannot print only names or real IDs in default format"));
if (argc - optind == 1)
{
struct passwd *pwd = getpwnam (argv[optind]);
@@ -183,6 +222,8 @@ main (int argc, char **argv)
print_group (use_real ? rgid : egid);
else if (just_group_list)
print_group_list (argv[optind]);
else if (just_context)
fputs (context, stdout);
else
print_full_info (argv[optind]);
putchar ('\n');
@@ -385,4 +426,6 @@ print_full_info (const char *username)
free (groups);
}
#endif /* HAVE_GETGROUPS */
if (context != NULL)
printf (" context=%s", context);
}

View File

@@ -24,6 +24,7 @@
#include <signal.h>
#include <pwd.h>
#include <grp.h>
#include <selinux/selinux.h>
#include "system.h"
#include "backupfile.h"
@@ -35,6 +36,7 @@
#include "mkdir-p.h"
#include "modechange.h"
#include "quote.h"
#include "quotearg.h"
#include "savewd.h"
#include "stat-time.h"
#include "utimens.h"
@@ -49,6 +51,9 @@
# include <sys/wait.h>
#endif
static int selinux_enabled = 0;
static bool use_default_selinux_context = true;
#if ! HAVE_ENDGRENT
# define endgrent() ((void) 0)
#endif
@@ -121,15 +126,28 @@ static bool strip_files;
/* If true, install a directory instead of a regular file. */
static bool dir_arg;
/* For long options that have no equivalent short option, use a
non-character as a pseudo short option, starting with CHAR_MAX + 1. */
enum
{
PRESERVE_CONTEXT_OPTION = CHAR_MAX + 1
};
static struct option const long_options[] =
{
{"backup", optional_argument, NULL, 'b'},
{GETOPT_SELINUX_CONTEXT_OPTION_DECL},
{"directory", no_argument, NULL, 'd'},
{"group", required_argument, NULL, 'g'},
{"mode", required_argument, NULL, 'm'},
{"no-target-directory", no_argument, NULL, 'T'},
{"owner", required_argument, NULL, 'o'},
{"preserve-timestamps", no_argument, NULL, 'p'},
{"preserve-context", no_argument, NULL, PRESERVE_CONTEXT_OPTION},
/* Continue silent support for --preserve_context until Jan 2008. FIXME-obs
After that, FIXME-obs: warn in, say, late 2008, and disable altogether
a year or two later. */
{"preserve_context", no_argument, NULL, PRESERVE_CONTEXT_OPTION},
{"strip", no_argument, NULL, 's'},
{"suffix", required_argument, NULL, 'S'},
{"target-directory", required_argument, NULL, 't'},
@@ -156,6 +174,7 @@ cp_option_init (struct cp_options *x)
x->preserve_mode = false;
x->preserve_timestamps = false;
x->require_preserve = false;
x->require_preserve_context = false;
x->recursive = false;
x->sparse_mode = SPARSE_AUTO;
x->symbolic_link = false;
@@ -169,11 +188,47 @@ cp_option_init (struct cp_options *x)
x->stdin_tty = false;
x->update = false;
x->preserve_security_context = false;
x->verbose = false;
x->dest_info = NULL;
x->src_info = NULL;
}
/* Modify file context to match the specified policy.
If an error occurs the file will remain with the default directory
context. */
static void
setdefaultfilecon (char const *file)
{
struct stat st;
security_context_t scontext = NULL;
if (selinux_enabled != 1)
{
/* Indicate no context found. */
return;
}
if (lstat (file, &st) != 0)
return;
/* If there's an error determining the context, or it has none,
return to allow default context */
if ((matchpathcon (file, st.st_mode, &scontext) != 0) ||
(strcmp (scontext, "<<none>>") == 0))
{
if (scontext != NULL)
freecon (scontext);
return;
}
if (lsetfilecon (file, scontext) < 0 && errno != ENOTSUP)
error (0, errno,
_("warning: %s: failed to change context to %s"),
quotearg_colon (file), scontext);
freecon (scontext);
return;
}
/* FILE is the last operand of this command. Return true if FILE is a
directory. But report an error there is a problem accessing FILE,
or if FILE does not exist but would have to refer to an existing
@@ -222,6 +277,9 @@ main (int argc, char **argv)
bool no_target_directory = false;
int n_files;
char **file;
security_context_t scontext = NULL;
/* set iff kernel has extra selinux system calls */
selinux_enabled = (0 < is_selinux_enabled ());
initialize_main (&argc, &argv);
program_name = argv[0];
@@ -243,7 +301,7 @@ main (int argc, char **argv)
we'll actually use backup_suffix_string. */
backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
while ((optc = getopt_long (argc, argv, "bcsDdg:m:o:pt:TvS:", long_options,
while ((optc = getopt_long (argc, argv, "bcsDdg:m:o:pt:TvS:Z:", long_options,
NULL)) != -1)
{
switch (optc)
@@ -305,6 +363,27 @@ main (int argc, char **argv)
case 'T':
no_target_directory = true;
break;
case PRESERVE_CONTEXT_OPTION:
if ( ! selinux_enabled)
{
error (0, 0, _("Warning: ignoring --preserve-context; "
"this kernel is not SELinux-enabled."));
break;
}
x.preserve_security_context = true;
use_default_selinux_context = false;
break;
case 'Z':
if ( ! selinux_enabled)
{
error (0, 0, _("Warning: ignoring --context (-Z); "
"this kernel is not SELinux-enabled."));
break;
}
scontext = optarg;
use_default_selinux_context = false;
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
@@ -320,6 +399,11 @@ main (int argc, char **argv)
error (EXIT_FAILURE, 0,
_("target directory not allowed when installing a directory"));
if (x.preserve_security_context && scontext != NULL)
error (EXIT_FAILURE, 0,
_("cannot force target context to %s and preserve it"),
quote (scontext));
if (backup_suffix_string)
simple_backup_suffix = xstrdup (backup_suffix_string);
@@ -328,6 +412,11 @@ main (int argc, char **argv)
version_control_string)
: no_backups);
if (scontext && setfscreatecon (scontext) < 0)
error (EXIT_FAILURE, errno,
_("failed to set default file creation context to %s"),
quote (scontext));
n_files = argc - optind;
file = argv + optind;
@@ -503,6 +592,7 @@ copy_file (const char *from, const char *to, const struct cp_options *x)
static bool
change_attributes (char const *name)
{
bool ok = false;
/* chown must precede chmod because on some systems,
chown clears the set[ug]id bits for non-superusers,
resulting in incorrect permissions.
@@ -521,9 +611,12 @@ change_attributes (char const *name)
else if (chmod (name, mode) != 0)
error (0, errno, _("cannot change permissions of %s"), quote (name));
else
return true;
ok = true;
return false;
if (use_default_selinux_context)
setdefaultfilecon (name);
return ok;
}
/* Set the timestamps of file TO to match those of file FROM.
@@ -687,6 +780,11 @@ Mandatory arguments to long options are mandatory for short options too.\n\
-T, --no-target-directory treat DEST as a normal file\n\
-v, --verbose print the name of each directory as it is created\n\
"), stdout);
fputs (_("\
--preserve-context preserve SELinux security context\n\
-Z, --context=CONTEXT set SELinux security context of files and directories\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
fputs (_("\

View File

@@ -61,6 +61,7 @@
#include <pwd.h>
#include <getopt.h>
#include <signal.h>
#include <selinux/selinux.h>
/* Use SA_NOCLDSTOP as a proxy for whether the sigaction machinery is
present. */
@@ -167,24 +168,20 @@ struct fileinfo
zero. */
mode_t linkmode;
/* SELinux security context. */
security_context_t scontext;
bool stat_ok;
/* For symbolic link and color printing, true if linked-to file
exists, otherwise false. */
bool linkok;
#if USE_ACL
/* For long listings, true if the file has an access control list. */
/* For long listings, true if the file has an access control list,
or an SELinux security context. */
bool have_acl;
#endif
};
#if USE_ACL
# define FILE_HAS_ACL(F) ((F)->have_acl)
#else
# define FILE_HAS_ACL(F) 0
#endif
#define LEN_STR_PAIR(s) sizeof (s) - 1, s
/* Null is a valid character in a color indicator (think about Epson
@@ -320,14 +317,12 @@ static struct pending *pending_dirs;
static time_t current_time = TYPE_MINIMUM (time_t);
static int current_time_ns = -1;
static bool print_scontext;
/* Whether any of the files has an ACL. This affects the width of the
mode column. */
#if USE_ACL
static bool any_has_acl;
#else
enum { any_has_acl = false };
#endif
/* The number of columns to use for columns containing inode numbers,
block sizes, link counts, owners, groups, authors, major device
@@ -336,6 +331,7 @@ enum { any_has_acl = false };
static int inode_number_width;
static int block_size_width;
static int nlink_width;
static int scontext_width;
static int owner_width;
static int group_width;
static int author_width;
@@ -787,6 +783,7 @@ static struct option const long_options[] =
{"time-style", required_argument, NULL, TIME_STYLE_OPTION},
{"color", optional_argument, NULL, COLOR_OPTION},
{"block-size", required_argument, NULL, BLOCK_SIZE_OPTION},
{"context", no_argument, 0, 'Z'},
{"author", no_argument, NULL, AUTHOR_OPTION},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
@@ -1246,6 +1243,7 @@ main (int argc, char **argv)
format_needs_stat = sort_type == sort_time || sort_type == sort_size
|| format == long_format
|| print_scontext
|| print_block_size;
format_needs_type = (! format_needs_stat
&& (recursive
@@ -1439,6 +1437,7 @@ decode_switches (int argc, char **argv)
ignore_mode = IGNORE_DEFAULT;
ignore_patterns = NULL;
hide_patterns = NULL;
print_scontext = false;
/* FIXME: put this in a function. */
{
@@ -1514,7 +1513,7 @@ decode_switches (int argc, char **argv)
}
while ((c = getopt_long (argc, argv,
"abcdfghiklmnopqrstuvw:xABCDFGHI:LNQRST:UX1",
"abcdfghiklmnopqrstuvw:xABCDFGHI:LNQRST:UXZ1",
long_options, NULL)) != -1)
{
switch (c)
@@ -1813,6 +1812,10 @@ decode_switches (int argc, char **argv)
file_output_block_size = output_block_size = 1;
break;
case 'Z':
print_scontext = true;
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
@@ -2516,18 +2519,22 @@ clear_files (void)
struct fileinfo *f = sorted_file[i];
free (f->name);
free (f->linkname);
if (f->scontext)
{
freecon (f->scontext);
f->scontext = NULL;
}
}
cwd_n_used = 0;
#if USE_ACL
any_has_acl = false;
#endif
inode_number_width = 0;
block_size_width = 0;
nlink_width = 0;
owner_width = 0;
group_width = 0;
author_width = 0;
scontext_width = 0;
major_device_number_width = 0;
minor_device_number_width = 0;
file_size_width = 0;
@@ -2589,9 +2596,11 @@ gobble_file (char const *name, enum filetype type, ino_t inode,
)))))
{
/* FIXME-c99: move this decl "down", once ls.c stabilizes. */
bool file_has_security_context = false;
/* Absolute name of this file. */
char *absolute_name;
bool do_deref;
int err;
if (name[0] == '/' || dirname[0] == 0)
@@ -2606,6 +2615,7 @@ gobble_file (char const *name, enum filetype type, ino_t inode,
{
case DEREF_ALWAYS:
err = stat (absolute_name, &f->stat);
do_deref = true;
break;
case DEREF_COMMAND_LINE_ARGUMENTS:
@@ -2614,6 +2624,7 @@ gobble_file (char const *name, enum filetype type, ino_t inode,
{
bool need_lstat;
err = stat (absolute_name, &f->stat);
do_deref = true;
if (dereference == DEREF_COMMAND_LINE_ARGUMENTS)
break;
@@ -2632,9 +2643,26 @@ gobble_file (char const *name, enum filetype type, ino_t inode,
default: /* DEREF_NEVER */
err = lstat (absolute_name, &f->stat);
do_deref = false;
break;
}
if (err == 0 && print_scontext)
{
int attr_len = (do_deref
? getfilecon (absolute_name, &f->scontext)
: lgetfilecon (absolute_name, &f->scontext));
err = (attr_len < 0);
file_has_security_context = (err == 0);
/* When requesting security context information, don't make
ls fail just because the file (even a command line argument)
isn't on the right type of file system. I.e., a getfilecon
failure isn't in the same class as a stat failure. */
if (err && (errno == ENOTSUP || errno == ENODATA))
err = 0;
}
if (err != 0)
{
/* Failure to stat a command line argument leads to
@@ -2653,16 +2681,14 @@ gobble_file (char const *name, enum filetype type, ino_t inode,
f->stat_ok = true;
#if USE_ACL
if (format == long_format)
{
int n = file_has_acl (absolute_name, &f->stat);
f->have_acl = (0 < n);
f->have_acl = (0 < n || file_has_security_context);
any_has_acl |= f->have_acl;
if (n < 0)
error (0, errno, "%s", quotearg_colon (absolute_name));
}
#endif
if (S_ISLNK (f->stat.st_mode)
&& (format == long_format || check_symlink_color))
@@ -2738,6 +2764,13 @@ gobble_file (char const *name, enum filetype type, ino_t inode,
author_width = len;
}
if (print_scontext)
{
int len = f->scontext ? strlen (f->scontext) : 0;
if (scontext_width < len)
scontext_width = len;
}
{
char buf[INT_BUFSIZE_BOUND (uintmax_t)];
int len = strlen (umaxtostr (f->stat.st_nlink, buf));
@@ -3387,7 +3420,7 @@ print_long_format (const struct fileinfo *f)
struct tm *when_local;
/* Compute the mode string, except remove the trailing space if no
files in this directory have ACLs. */
file in this directory has an ACL or SELinux security context. */
if (f->stat_ok)
filemodestring (&f->stat, modebuf);
else
@@ -3398,7 +3431,7 @@ print_long_format (const struct fileinfo *f)
}
if (! any_has_acl)
modebuf[10] = '\0';
else if (FILE_HAS_ACL (f))
else if (f->have_acl)
modebuf[10] = '+';
switch (time_type)
@@ -3463,7 +3496,7 @@ print_long_format (const struct fileinfo *f)
DIRED_INDENT ();
if (print_owner | print_group | print_author)
if (print_owner | print_group | print_author | print_scontext)
{
DIRED_FPUTS (buf, stdout, p - buf);
@@ -3476,6 +3509,10 @@ print_long_format (const struct fileinfo *f)
if (print_author)
format_user (f->stat.st_author, author_width, f->stat_ok);
if (print_scontext)
format_user_or_group ((f->scontext ? f->scontext : "?"),
0, scontext_width);
p = buf;
}
@@ -3812,6 +3849,10 @@ print_file_name_and_frills (const struct fileinfo *f)
human_readable (ST_NBLOCKS (f->stat), buf, human_output_opts,
ST_NBLOCKSIZE, output_block_size));
if (print_scontext)
printf ("%*s ", format == with_commas ? 0 : scontext_width,
(f->scontext ? f->scontext : "?"));
print_name_with_quoting (f->name, FILE_OR_LINK_MODE (f), f->linkok,
f->stat_ok, f->filetype, NULL);
@@ -3975,6 +4016,9 @@ length_of_file_name_and_frills (const struct fileinfo *f)
output_block_size))
: block_size_width);
if (print_scontext)
len += 1 + (format == with_commas ? strlen (f->scontext) : scontext_width);
quote_name (NULL, f->name, filename_quoting_options, &name_width);
len += name_width;
@@ -4403,6 +4447,7 @@ Mandatory arguments to long options are mandatory for short options too.\n\
-w, --width=COLS assume screen width instead of current value\n\
-x list entries by lines instead of by columns\n\
-X sort alphabetically by entry extension\n\
-Z, --context print any SELinux security context of each file\n\
-1 list one file per line\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);

View File

@@ -1,5 +1,5 @@
/* mkdir -- make directories
Copyright (C) 90, 1995-2002, 2004, 2005, 2006 Free Software Foundation, Inc.
Copyright (C) 90, 1995-2002, 2004-2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <getopt.h>
#include <sys/types.h>
#include <selinux/selinux.h>
#include "system.h"
#include "error.h"
@@ -40,6 +41,7 @@ char *program_name;
static struct option const longopts[] =
{
{GETOPT_SELINUX_CONTEXT_OPTION_DECL},
{"mode", required_argument, NULL, 'm'},
{"parents", no_argument, NULL, 'p'},
{"verbose", no_argument, NULL, 'v'},
@@ -68,6 +70,8 @@ Mandatory arguments to long options are mandatory for short options too.\n\
-m, --mode=MODE set file mode (as in chmod), not a=rwx - umask\n\
-p, --parents no error if existing, make parent directories as needed\n\
-v, --verbose print a message for each created directory\n\
-Z, --context=CTX set the SELinux security context of each created\n\
directory to CTX\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
@@ -140,7 +144,9 @@ main (int argc, char **argv)
{
const char *specified_mode = NULL;
int optc;
security_context_t scontext = NULL;
struct mkdir_options options;
options.make_ancestor_function = NULL;
options.mode = S_IRWXUGO;
options.mode_bits = 0;
@@ -154,7 +160,7 @@ main (int argc, char **argv)
atexit (close_stdout);
while ((optc = getopt_long (argc, argv, "pm:v", longopts, NULL)) != -1)
while ((optc = getopt_long (argc, argv, "pm:vZ:", longopts, NULL)) != -1)
{
switch (optc)
{
@@ -167,6 +173,9 @@ main (int argc, char **argv)
case 'v': /* --verbose */
options.created_directory_format = _("created directory %s");
break;
case 'Z':
scontext = optarg;
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
@@ -180,6 +189,11 @@ main (int argc, char **argv)
usage (EXIT_FAILURE);
}
if (scontext && setfscreatecon (scontext) < 0)
error (EXIT_FAILURE, errno,
_("failed to set default file creation context to %s"),
quote (optarg));
if (options.make_ancestor_function || specified_mode)
{
mode_t umask_value = umask (0);

View File

@@ -1,5 +1,5 @@
/* mkfifo -- make fifo's (named pipes)
Copyright (C) 90, 91, 1995-2006 Free Software Foundation, Inc.
Copyright (C) 90, 91, 1995-2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <getopt.h>
#include <sys/types.h>
#include <selinux/selinux.h>
#include "system.h"
#include "error.h"
@@ -37,6 +38,7 @@ char *program_name;
static struct option const longopts[] =
{
{GETOPT_SELINUX_CONTEXT_OPTION_DECL},
{"mode", required_argument, NULL, 'm'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
@@ -55,6 +57,9 @@ usage (int status)
fputs (_("\
Create named pipes (FIFOs) with the given NAMEs.\n\
\n\
"), stdout);
fputs (_("\
-Z, --context=CTX set the SELinux security context of each NAME to CTX\n\
"), stdout);
fputs (_("\
Mandatory arguments to long options are mandatory for short options too.\n\
@@ -76,6 +81,7 @@ main (int argc, char **argv)
char const *specified_mode = NULL;
int exit_status = EXIT_SUCCESS;
int optc;
security_context_t scontext = NULL;
initialize_main (&argc, &argv);
program_name = argv[0];
@@ -85,13 +91,16 @@ main (int argc, char **argv)
atexit (close_stdout);
while ((optc = getopt_long (argc, argv, "m:", longopts, NULL)) != -1)
while ((optc = getopt_long (argc, argv, "m:Z:", longopts, NULL)) != -1)
{
switch (optc)
{
case 'm':
specified_mode = optarg;
break;
case 'Z':
scontext = optarg;
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
@@ -105,6 +114,11 @@ main (int argc, char **argv)
usage (EXIT_FAILURE);
}
if (scontext && setfscreatecon (scontext) < 0)
error (EXIT_FAILURE, errno,
_("failed to set default file creation context to %s"),
quote (optarg));
newmode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (specified_mode)
{

View File

@@ -1,5 +1,5 @@
/* mknod -- make special files
Copyright (C) 90, 91, 1995-2006 Free Software Foundation, Inc.
Copyright (C) 90, 91, 1995-2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <getopt.h>
#include <sys/types.h>
#include <selinux/selinux.h>
#include "system.h"
#include "error.h"
@@ -38,6 +39,7 @@ char *program_name;
static struct option const longopts[] =
{
{GETOPT_SELINUX_CONTEXT_OPTION_DECL},
{"mode", required_argument, NULL, 'm'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
@@ -57,6 +59,9 @@ usage (int status)
fputs (_("\
Create the special file NAME of the given TYPE.\n\
\n\
"), stdout);
fputs(_("\
-Z, --context=CTX set the SELinux security context of NAME to CTX\n\
"), stdout);
fputs (_("\
Mandatory arguments to long options are mandatory for short options too.\n\
@@ -92,6 +97,7 @@ main (int argc, char **argv)
int optc;
int expected_operands;
mode_t node_type;
security_context_t scontext = NULL;
initialize_main (&argc, &argv);
program_name = argv[0];
@@ -101,13 +107,16 @@ main (int argc, char **argv)
atexit (close_stdout);
while ((optc = getopt_long (argc, argv, "m:", longopts, NULL)) != -1)
while ((optc = getopt_long (argc, argv, "m:Z:", longopts, NULL)) != -1)
{
switch (optc)
{
case 'm':
specified_mode = optarg;
break;
case 'Z':
scontext = optarg;
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
@@ -157,6 +166,11 @@ main (int argc, char **argv)
usage (EXIT_FAILURE);
}
if (scontext && setfscreatecon (scontext) < 0)
error (EXIT_FAILURE, errno,
_("failed to set default file creation context to %s"),
quote (optarg));
/* Only check the first character, to allow mnemonic usage like
`mknod /dev/rst0 character 18 0'. */

View File

@@ -22,6 +22,7 @@
#include <getopt.h>
#include <sys/types.h>
#include <assert.h>
#include <selinux/selinux.h>
#include "system.h"
#include "argmatch.h"
@@ -113,6 +114,8 @@ rm_option_init (struct rm_options *x)
static void
cp_option_init (struct cp_options *x)
{
bool selinux_enabled = (0 < is_selinux_enabled ());
x->copy_as_regular = false; /* FIXME: maybe make this an option */
x->dereference = DEREF_NEVER;
x->unlink_dest_before_opening = false;
@@ -126,7 +129,9 @@ cp_option_init (struct cp_options *x)
x->preserve_links = true;
x->preserve_mode = true;
x->preserve_timestamps = true;
x->preserve_security_context = selinux_enabled;
x->require_preserve = false; /* FIXME: maybe make this an option */
x->require_preserve_context = false;
x->recursive = true;
x->sparse_mode = SPARSE_AUTO; /* FIXME: maybe make this an option */
x->symbolic_link = false;

249
src/runcon.c Normal file
View File

@@ -0,0 +1,249 @@
/*
* runcon [ context |
* ( [ -c ] [ -r role ] [-t type] [ -u user ] [ -l levelrange ] )
* command [arg1 [arg2 ...] ]
*
* attempt to run the specified command with the specified context.
*
* -r role : use the current context with the specified role
* -t type : use the current context with the specified type
* -u user : use the current context with the specified user
* -l level : use the current context with the specified level range
* -c : compute process transition context before modifying
*
* Contexts are interpreted as follows:
*
* Number of MLS
* components system?
*
* 1 - type
* 2 - role:type
* 3 Y role:type:range
* 3 N user:role:type
* 4 Y user:role:type:range
* 4 N error
*/
#include <config.h>
#include <stdio.h>
#include <getopt.h>
#include <selinux/selinux.h>
#include <selinux/context.h>
#ifdef HAVE_SELINUX_FLASK_H
# include <selinux/flask.h>
#else
# define SECCLASS_PROCESS 0
#endif
#include <sys/types.h>
#include "system.h"
#include "error.h"
#include "quote.h"
#include "quotearg.h"
/* The official name of this program (e.g., no `g' prefix). */
#define PROGRAM_NAME "runcon"
#define AUTHORS "Russell Coker"
static struct option long_options[] = {
{"role", required_argument, NULL, 'r'},
{"type", required_argument, NULL, 't'},
{"user", required_argument, NULL, 'u'},
{"range", required_argument, NULL, 'l'},
{"compute", no_argument, NULL, 'c'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
};
/* The name the program was run with. */
char *program_name;
void
usage (int status)
{
if (status != EXIT_SUCCESS)
fprintf (stderr, _("Try `%s --help' for more information.\n"),
program_name);
else
{
printf (_("\
Usage: %s CONTEXT COMMAND [args]\n\
or: %s [ -c ] [-u USER] [-r ROLE] [-t TYPE] [-l RANGE] COMMAND [args]\n\
"), program_name, program_name);
fputs (_("\
Run a program in a different security context.\n\
With neither CONTEXT nor COMMAND, print the current security context.\n\
\n\
CONTEXT Complete security context\n\
-c, --compute compute process transition context before modifying\n\
-t, --type=TYPE type (for same role as parent)\n\
-u, --user=USER user identity\n\
-r, --role=ROLE role\n\
-l, --range=RANGE levelrange\n\
\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
}
exit (status);
}
int
main (int argc, char **argv, char **envp)
{
char *role = NULL;
char *range = NULL;
char *user = NULL;
char *type = NULL;
char *context = NULL;
security_context_t cur_context = NULL;
security_context_t file_context = NULL;
security_context_t new_context = NULL;
bool compute_trans = false;
context_t con;
initialize_main (&argc, &argv);
program_name = argv[0];
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
atexit (close_stdout);
while (1)
{
int option_index = 0;
int c = getopt_long (argc, argv, "+r:t:u:l:c", long_options,
&option_index);
if (c == -1)
break;
switch (c)
{
case 'r':
if (role)
error (EXIT_FAILURE, 0, _("multiple roles"));
role = optarg;
break;
case 't':
if (type)
error (EXIT_FAILURE, 0, _("multiple types"));
type = optarg;
break;
case 'u':
if (user)
error (EXIT_FAILURE, 0, _("multiple users"));
user = optarg;
break;
case 'l':
if (range)
error (EXIT_FAILURE, 0, _("multiple levelranges"));
range = optarg;
break;
case 'c':
compute_trans = true;
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
usage (EXIT_FAILURE);
break;
}
}
if (argc - optind == 0)
{
if (getcon (&cur_context) < 0)
error (EXIT_FAILURE, errno, _("failed to get current context"));
fputs (cur_context, stdout);
fputc ('\n', stdout);
exit (EXIT_SUCCESS);
}
if (!(user || role || type || range || compute_trans))
{
if (optind >= argc)
{
error (0, 0, _("you must specify -c, -t, -u, -l, -r, or context"));
usage (1);
}
context = argv[optind++];
}
if (optind >= argc)
{
error (0, 0, _("no command specified"));
usage (1);
}
if (is_selinux_enabled () != 1)
error (EXIT_FAILURE, 0,
_("runcon may be used only on a SELinux kernel"));
if (context)
{
con = context_new (context);
if (!con)
error (EXIT_FAILURE, errno, _("failed to create security context: %s"),
quotearg_colon (context));
}
else
{
if (getcon (&cur_context) < 0)
error (EXIT_FAILURE, errno, _("failed to get current context"));
/* We will generate context based on process transition */
if (compute_trans)
{
/* Get context of file to be executed */
if (getfilecon (argv[optind], &file_context) == -1)
error (EXIT_FAILURE, errno,
_("failed to get security context of %s"),
quote (argv[optind]));
/* compute result of process transition */
if (security_compute_create (cur_context, file_context,
SECCLASS_PROCESS, &new_context) != 0)
error (EXIT_FAILURE, errno,
_("failed to compute a new context"));
/* free contexts */
freecon (file_context);
freecon (cur_context);
/* set cur_context equal to new_context */
cur_context = new_context;
}
con = context_new (cur_context);
if (!con)
error (EXIT_FAILURE, errno, _("failed to create security context: %s"),
quotearg_colon (cur_context));
if (user && context_user_set (con, user))
error (EXIT_FAILURE, errno, _("failed to set new user %s"), user);
if (type && context_type_set (con, type))
error (EXIT_FAILURE, errno, _("failed to set new type %s"), type);
if (range && context_range_set (con, range))
error (EXIT_FAILURE, errno, _("failed to set new range %s"), range);
if (role && context_role_set (con, role))
error (EXIT_FAILURE, errno, _("failed to set new role %s"), role);
}
if (security_check_context (context_str (con)) < 0)
error (EXIT_FAILURE, errno, _("invalid context: %s"),
quotearg_colon (context_str (con)));
if (setexeccon (context_str (con)) != 0)
error (EXIT_FAILURE, errno, _("unable to set security context %s"),
quote (context_str (con)));
if (cur_context != NULL)
freecon (cur_context);
execvp (argv[optind], argv + optind);
{
int exit_status = (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
error (0, errno, "%s", argv[optind]);
exit (exit_status);
}
}

View File

@@ -54,6 +54,7 @@
#elif HAVE_OS_H /* BeOS */
# include <fs_info.h>
#endif
#include <selinux/selinux.h>
#include "system.h"
@@ -158,6 +159,7 @@ enum
};
static struct option const long_options[] = {
{"context", no_argument, 0, 'Z'},
{"dereference", no_argument, NULL, 'L'},
{"file-system", no_argument, NULL, 'f'},
{"filesystem", no_argument, NULL, 'f'}, /* obsolete and undocumented alias */
@@ -171,6 +173,9 @@ static struct option const long_options[] = {
char *program_name;
/* Whether to follow symbolic links; True for --dereference (-L). */
static bool follow_links;
/* Whether to interpret backslash-escape sequences.
True for --printf=FMT, not for --format=FMT (-c). */
static bool interpret_backslash_escapes;
@@ -394,6 +399,26 @@ out_uint_x (char *pformat, size_t prefix_len, uintmax_t arg)
printf (pformat, arg);
}
/* Very specialized function (modifies FORMAT), just so as to avoid
duplicating this code between both print_statfs and print_stat. */
static void
out_file_context (char const *filename, char *pformat, size_t prefix_len)
{
char *scontext;
if ((follow_links
? getfilecon (filename, &scontext)
: lgetfilecon (filename, &scontext)) < 0)
{
error (0, errno, _("failed to get security context of %s"),
quote (filename));
scontext = NULL;
}
strcpy (pformat + prefix_len, "s");
printf (pformat, (scontext ? scontext : "?"));
if (scontext)
freecon (scontext);
}
/* print statfs info */
static void
print_statfs (char *pformat, size_t prefix_len, char m, char const *filename,
@@ -472,7 +497,9 @@ print_statfs (char *pformat, size_t prefix_len, char m, char const *filename,
case 'd':
out_int (pformat, prefix_len, statfsbuf->f_ffree);
break;
case 'C':
out_file_context (filename, pformat, prefix_len);
break;
default:
fputc ('?', stdout);
break;
@@ -595,6 +622,9 @@ print_stat (char *pformat, size_t prefix_len, char m,
else
out_uint (pformat, prefix_len, statbuf->st_ctime);
break;
case 'C':
out_file_context (filename, pformat, prefix_len);
break;
default:
fputc ('?', stdout);
break;
@@ -774,8 +804,7 @@ do_statfs (char const *filename, bool terse, char const *format)
/* stat the file and print what we find */
static bool
do_stat (char const *filename, bool follow_links, bool terse,
char const *format)
do_stat (char const *filename, bool terse, char const *format)
{
struct stat statbuf;
@@ -853,6 +882,7 @@ The valid format sequences for files (without --file-system):\n\
%A Access rights in human readable form\n\
%b Number of blocks allocated (see %B)\n\
%B The size in bytes of each block reported by %b\n\
%C SELinux security context string\n\
"), stdout);
fputs (_("\
%d Device number in decimal\n\
@@ -892,6 +922,7 @@ Valid format sequences for file systems:\n\
%c Total file nodes in file system\n\
%d Free file nodes in file system\n\
%f Free blocks in file system\n\
%C SELinux security context string\n\
"), stdout);
fputs (_("\
%i File System ID in hex\n\
@@ -913,7 +944,6 @@ main (int argc, char *argv[])
{
int c;
int i;
bool follow_links = false;
bool fs = false;
bool terse = false;
char *format = NULL;
@@ -927,7 +957,7 @@ main (int argc, char *argv[])
atexit (close_stdout);
while ((c = getopt_long (argc, argv, "c:fLt", long_options, NULL)) != -1)
while ((c = getopt_long (argc, argv, "c:fLtZ", long_options, NULL)) != -1)
{
switch (c)
{
@@ -955,6 +985,11 @@ main (int argc, char *argv[])
terse = true;
break;
case 'Z': /* FIXME: remove in 2008, warn in 2007 */
/* Ignored, for compatibility with distributions
that implemented this before upstream. */
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
@@ -973,7 +1008,7 @@ main (int argc, char *argv[])
for (i = optind; i < argc; i++)
ok &= (fs
? do_statfs (argv[i], terse, format)
: do_stat (argv[i], follow_links, terse, format));
: do_stat (argv[i], terse, format));
exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
}

View File

@@ -399,6 +399,8 @@ enum
"help", no_argument, NULL, GETOPT_HELP_CHAR
#define GETOPT_VERSION_OPTION_DECL \
"version", no_argument, NULL, GETOPT_VERSION_CHAR
#define GETOPT_SELINUX_CONTEXT_OPTION_DECL \
"context", required_argument, NULL, 'Z'
#define case_GETOPT_HELP_CHAR \
case GETOPT_HELP_CHAR: \

View File

@@ -18,7 +18,7 @@ EXTRA_DIST = \
$(TESTS) Coreutils.pm Makefile.am.in README acl envvar-check \
expensive group-names input-tty lang-default mk-script \
other-fs-tmpdir priv-check \
rwx-to-mode sample-test setgid-check sparse-file \
rwx-to-mode sample-test selinux setgid-check sparse-file \
umask-check very-expensive
## N O T E :: Please do not add new tests/ directories.
@@ -30,7 +30,7 @@ SUBDIRS = \
tsort unexpand uniq wc
## N O T E :: Please do not add new directories.
all_t = t1 t2 t3 t4 t5 t6 t7
all_t = t1 t2 t3 t4 t5 t6 t7 t8 t9
.PHONY: check-root $(all_t)
check-root: $(all_t)
@@ -48,6 +48,10 @@ t6:
cd rm && $(MAKE) check TESTS=one-file-system
t7:
cd ls && $(MAKE) check TESTS=nameless-uid
t8:
cd misc && $(MAKE) check TESTS=chcon
t9:
cd cp && $(MAKE) check TESTS=cp-a-selinux
check-recursive: root-hint

View File

@@ -51,7 +51,7 @@ for src in u g o; do
for dest in u g o; do
test $dest = $src && continue
chmod a=,$src=rwx,$dest=$src,$src= f || fail=1
set _ `ls -l f`; shift; actual_perms=$1
actual_perms=`ls -l f|cut -b-10`
expected_perms=`eval 'echo \$expected_'$dest`
test "$actual_perms" = "$expected_perms" || fail=1
done
@@ -59,7 +59,7 @@ done
umask 027
chmod a=,u=rwx,=u f || fail=1
set _ `ls -l f`; shift; actual_perms=$1
actual_perms=`ls -l f|cut -b-10`
test "$actual_perms" = "-rwxr-x---" || fail=1
(exit $fail); exit $fail

View File

@@ -18,6 +18,7 @@
# 02110-1301, USA.
TESTS = \
cp-a-selinux \
file-perm-race parent-perm-race \
backup-dir \
src-base-dot \

94
tests/cp/cp-a-selinux Executable file
View File

@@ -0,0 +1,94 @@
#!/bin/sh
# Ensure that cp -a and cp --preserve=context work properly.
# In particular, test on a writable NFS partition.
# Copyright (C) 2007 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
if test "$VERBOSE" = yes; then
set -x
cp --version
fi
. $srcdir/../envvar-check
. $srcdir/../lang-default
. $srcdir/../selinux
PRIV_CHECK_ARG=require-root . $srcdir/../priv-check
pwd=`pwd`
t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
trap 'status=$?; cd "$pwd"; umount $tmp/mnt; chmod -R u+rwx $t0 && rm -rf $t0 && exit $status' 0
trap '(exit $?); exit $?' 1 2 13 15
framework_failure=0
mkdir -p $tmp || framework_failure=1
cd $tmp || framework_failure=1
# Create a file system, then mount it with the context=... option.
dd if=/dev/zero of=blob bs=8192 count=200 > /dev/null 2>&1 \
|| framework_failure=1
mkdir mnt || framework_failure=1
mkfs -t ext2 -F blob > /dev/null 2>&1 || framework_failure=1
mount -oloop,context=system_u:object_r:removable_t blob mnt \
|| framework_failure=1
cd mnt || framework_failure=1
echo > f || framework_failure=1
echo > g || framework_failure=1
if test $framework_failure = 1; then
echo "$0: failure in testing framework" 1>&2
(exit 1); exit 1
fi
fail=0
# /bin/cp from coreutils-6.7-3.fc7 would fail this test by letting cp
# succeed (giving no diagnostics), yet leaving the destination file empty.
cp -a f g 2>err || fail=1
test -s g || fail=1 # The destination file must not be empty.
test -s err && fail=1 # There must be no stderr output.
rm -f g err
echo > g
# =====================================================
# Here, we expect cp to fail, because it cannot set the SELinux
# security context through NFS or a mount with fixed context.
cp --preserve=context f g 2> out && fail=1
# Here, we *do* expect the destination to be empty.
test -s g && fail=1
# An alternative to the current approach would be to run in a confined
# domain (maybe creating/loading it) that lacks the required permissions
# to the file type.
# Note: this test could also be run by a regular (non-root) user in an
# NFS mounted directory. When doing that, I get this diagnostic:
# cp: failed to set the security context of `g' to `system_u:object_r:nfs_t': \
# Operation not supported
sed "s/ .g' to .*//" out > k
mv k out
cat <<\EOF > exp || fail=1
cp: failed to set the security context of
EOF
cmp out exp || fail=1
test $fail = 1 && diff out exp 2> /dev/null
(exit $fail); exit $fail

View File

@@ -75,8 +75,8 @@ test -d d/f && fail=1
# Check that re_protect works.
chmod go=w d/a
cp -a --parents d/a/b/c e || fail=1
p=`ls -ld e/d|sed 's/ .*//'`; case $p in drwxr-xr-x);; *) fail=1;; esac
p=`ls -ld e/d/a|sed 's/ .*//'`; case $p in drwx-w--w-);; *) fail=1;; esac
p=`ls -ld e/d/a/b/c|sed 's/ .*//'`; case $p in drwxr-xr-x);; *) fail=1;; esac
p=`ls -ld e/d|cut -b-10`; case $p in drwxr-xr-x);; *) fail=1;; esac
p=`ls -ld e/d/a|cut -b-10`; case $p in drwx-w--w-);; *) fail=1;; esac
p=`ls -ld e/d/a/b/c|cut -b-10`; case $p in drwxr-xr-x);; *) fail=1;; esac
(exit $fail); exit $fail

View File

@@ -52,9 +52,8 @@ cp -pR D DD > /dev/null 2>&1 && fail=1
# Permissions on DD must be `dr-x------'
set X `ls -ld DD`
shift
test "$1" = dr-x------ || fail=1
mode=`ls -ld DD|cut -b-10`
test "$mode" = dr-x------ || fail=1
chmod 0 D
ln -s D/D symlink

View File

@@ -98,7 +98,7 @@ rm -rf a b c d
touch a; chmod 731 a
umask 077
cp -a --no-preserve=mode a b
set _ `ls -l b`; shift; mode=$1
mode=`ls -l b|cut -b-10`
test "$mode" = "-rwx------" || fail=1
umask 022
# --------------------------------------

View File

@@ -2,8 +2,7 @@
# Make sure all these programs work properly
# when invoked with --help or --version.
# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
# Foundation, Inc.
# Copyright (C) 2000-2007 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -72,6 +71,8 @@ for lang in C fr da; do
# Skip `test'; it doesn't accept --help or --version.
test $i = test && continue;
test $i = chcon && continue;
test $i = runcon && continue;
# false fails even when invoked with --help or --version.
if test $i = false; then
@@ -197,7 +198,7 @@ lbracket_args=": ]"
for i in $all_programs; do
# Skip these.
case $i in chroot|stty|tty|false) continue;; esac
case $i in chroot|stty|tty|false|chcon|runcon) continue;; esac
rm -rf $tmp_in $tmp_in2 $tmp_dir $tmp_out
echo > $tmp_in

View File

@@ -98,9 +98,8 @@ ginstall -s -c -m 555 $dd $dir || fail=1
test -f $dd || fail=1
# Make sure that the destination file has the requested permissions.
set X `ls -l $dir/$dd`
shift
test "$1" = -r-xr-xr-x || fail=1
mode=`ls -l $dir/$dd|cut -b-10`
test "$mode" = -r-xr-xr-x || fail=1
# These failed in coreutils CVS from 2004-06-25 to 2004-08-11.
ginstall -d . || fail=1

View File

@@ -1,6 +1,6 @@
# Make miscellaneous coreutils tests. -*-Makefile-*-
# Copyright (C) 200-2007 Free Software Foundation, Inc.
# Copyright (C) 2001-2007 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -43,6 +43,9 @@ TESTS = \
pr \
df-P \
pwd-unreadable-parent \
chcon \
chcon-fail \
selinux \
cut \
wc-files0-from \
wc-files0 \
@@ -70,6 +73,7 @@ TESTS = \
printf \
printf-hex \
pwd-long \
runcon-no-reorder \
sha224sum \
sha256sum \
sha384sum \

73
tests/misc/chcon Executable file
View File

@@ -0,0 +1,73 @@
#!/bin/sh
# exercise chcon
if test "$VERBOSE" = yes; then
set -x
chcon --version
fi
. $srcdir/../lang-default
PRIV_CHECK_ARG=require-root . $srcdir/../priv-check
pwd=`pwd`
t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
trap 'status=$?; cd $pwd; chmod -R u+rwx $t0; rm -rf $t0 && exit $status' 0
trap '(exit $?); exit $?' 1 2 13 15
framework_failure=0
mkdir -p $tmp || framework_failure=1
cd $tmp || framework_failure=1
mkdir -p d/sub/s2 || framework_failure=1
touch f g d/sub/1 d/sub/2 || framework_failure=1
if test $framework_failure = 1; then
echo "$0: failure in testing framework" 1>&2
(exit 1); exit 1
fi
fail=0
# Set to a specified context.
u1=root
r1=object_r
t1=tmp_t
ctx=$u1:$r1:$t1
chcon $ctx f || fail=1
stat --printf='f|%C\n' f > out || fail=1
# Use --reference.
chcon --ref=f g || fail=1
stat --printf='g|%C\n' g >> out || fail=1
# Change the individual parts of the context, one by one.
u2=user_u
r2=object_r
t2=file_t
l2=SystemLow-SystemHigh
for i in --user=$u2 --role=$r2 --type=$t2 --range=$l2; do
chcon $i f || fail=1
stat --printf="f|$i|"'%C\n' f >> out || fail=1
done
# Same, but change back using the short-named options.
for i in -u$u1 -r$r1 -t$t1; do
chcon $i f || fail=1
stat --printf="f|$i|"'%C\n' f >> out || fail=1
done
cat <<EOF > exp || fail=1
f|$ctx
g|$ctx
f|--user=$u2|$u2:$r1:$t1
f|--role=$r2|$u2:$r2:$t1
f|--type=$t2|$u2:$r2:$t2
f|--range=$l2|$u2:$r2:$t2:$l2
f|-uroot|root:object_r:file_t:SystemLow-SystemHigh
f|-robject_r|root:object_r:file_t:SystemLow-SystemHigh
f|-ttmp_t|root:object_r:tmp_t:SystemLow-SystemHigh
EOF
cmp out exp || fail=1
test $fail = 1 && diff out exp 2> /dev/null
(exit $fail); exit $fail

41
tests/misc/chcon-fail Executable file
View File

@@ -0,0 +1,41 @@
#!/bin/sh
# Ensure that chcon fails when it should.
# These tests don't use any actual SE Linux syscalls.
if test "$VERBOSE" = yes; then
set -x
chcon --version
fi
. $srcdir/../lang-default
pwd=`pwd`
t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
trap 'status=$?; cd $pwd; chmod -R u+rwx $t0; rm -rf $t0 && exit $status' 0
trap '(exit $?); exit $?' 1 2 13 15
framework_failure=0
mkdir -p $tmp || framework_failure=1
cd $tmp || framework_failure=1
if test $framework_failure = 1; then
echo "$0: failure in testing framework" 1>&2
(exit 1); exit 1
fi
fail=0
# neither context nor file
chcon 2> /dev/null && fail=1
# No file
chcon CON 2> /dev/null && fail=1
# No file
touch f
chcon --reference=f 2> /dev/null && fail=1
# No file
chcon -u anyone 2> /dev/null && fail=1
(exit $fail); exit $fail

View File

@@ -42,15 +42,15 @@ fail=0
umask 777
mknod -m 734 f1 p || fail=1
set _ `ls -dgo f1`; shift; mode=$1
mode=`ls -dgo f1|cut -b-10`
test $mode = prwx-wxr-- || fail=1
mkfifo -m 734 f2 || fail=1
set _ `ls -dgo f2`; shift; mode=$1
mode=`ls -dgo f2|cut -b-10`
test $mode = prwx-wxr-- || fail=1
mkdir -m 734 f3 || fail=1
set _ `ls -dgo f3`; shift; mode=$1
mode=`ls -dgo f3|cut -b-10`
test $mode = drwx-wxr-- || test $mode = drwx-wsr-- || fail=1
(exit $fail); exit $fail

57
tests/misc/runcon-no-reorder Executable file
View File

@@ -0,0 +1,57 @@
#!/bin/sh
# Ensure that runcon does not reorder its arguments.
# Copyright (C) 2007 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
if test "$VERBOSE" = yes; then
set -x
runcon --version
fi
. $srcdir/../lang-default
pwd=`pwd`
t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
trap 'status=$?; cd "$pwd" && chmod -R u+rwx $t0 && rm -rf $t0 && exit $status' 0
trap '(exit $?); exit $?' 1 2 13 15
framework_failure=0
mkdir -p $tmp || framework_failure=1
cd $tmp || framework_failure=1
cat <<\EOF > exp || framework_failure=1
runcon: runcon may be used only on a SELinux kernel
EOF
if test $framework_failure = 1; then
echo "$0: failure in testing framework" 1>&2
(exit 1); exit 1
fi
fail=0
# This test works even on systems without SELinux.
# On such a system it fails with the above diagnostic, which is fine.
# Before the no-reorder change, it would have failed with a diagnostic
# about -j being an invalid option.
runcon -t unconfined_t true -j 2> out && : > exp
cmp out exp || fail=1
test $fail = 1 && diff out exp 2> /dev/null
(exit $fail); exit $fail

61
tests/misc/selinux Executable file
View File

@@ -0,0 +1,61 @@
#!/bin/sh
# Test SELinux-related options.
if test "$VERBOSE" = yes; then
set -x
chcon --version
cp --version
ls --version
mv --version
stat --version
fi
. $srcdir/../envvar-check
. $srcdir/../lang-default
. $srcdir/../selinux
PRIV_CHECK_ARG=require-non-root . $srcdir/../priv-check
pwd=`pwd`
t0=`echo "$0"|sed 's,.*/,,'`.tmp; tmp=$t0/$$
trap 'status=$?; cd $pwd; chmod -R u+rwx $t0; rm -rf $t0 && exit $status' 0
trap '(exit $?); exit $?' 1 2 13 15
framework_failure=0
mkdir -p $tmp || framework_failure=1
cd $tmp || framework_failure=1
# Create a regular file, dir, fifo.
touch f || framework_failure=1
mkdir d s1 s2 || framework_failure=1
mkfifo p || framework_failure=1
if test $framework_failure = 1; then
echo "$0: failure in testing framework" 1>&2
(exit 1); exit 1
fi
fail=0
ctx=root:object_r:tmp_t
# FIXME, what if $ctx is no different from the default. Not likely.
# give each a different context, via chcon
chcon $ctx f d p || fail=1
# inspect that context with both ls -Z and stat.
for i in d f p; do
c=`ls -dogZ $i|cut -d' ' -f3`; test x$c = x$ctx || fail=1
c=`stat --printf %C $i`; test x$c = x$ctx || fail=1
done
# Copy each to a new directory and ensure that context is preserved.
cp -r --preserve=all d f p s1 || fail=1
for i in d f p; do
c=`stat --printf %C s1/$i`; test x$c = x$ctx || fail=1
done
# Now, move each to a new directory and ensure that context is preserved.
mv d f p s2 || fail=1
for i in d f p; do
c=`stat --printf %C s2/$i`; test x$c = x$ctx || fail=1
done
(exit $fail); exit $fail

View File

@@ -65,12 +65,12 @@ d_mode_arg=`"$abs_srcdir/../rwx-to-mode" $d_mode_str`
mkdir -p -m $d_mode_arg a/b/c/d
# Make sure the permissions of `a' haven't been changed.
p=`ls -ld a|sed 's/ .*//'`; case $p in $mode_str);; *) fail=1;; esac
p=`ls -ld a|cut -b-10`; case $p in $mode_str);; *) fail=1;; esac
# `b's and `c's should reflect the umask
p=`ls -ld a/b|sed 's/ .*//'`; case $p in drwx------);; *) fail=1;; esac
p=`ls -ld a/b/c|sed 's/ .*//'`; case $p in drwx------);; *) fail=1;; esac
p=`ls -ld a/b|cut -b-10`; case $p in drwx------);; *) fail=1;; esac
p=`ls -ld a/b/c|cut -b-10`; case $p in drwx------);; *) fail=1;; esac
# `d's perms are determined by the -m argument.
p=`ls -ld a/b/c/d|sed 's/ .*//'`; case $p in $d_mode_str);; *) fail=1;; esac
p=`ls -ld a/b/c/d|cut -b-10`; case $p in $d_mode_str);; *) fail=1;; esac
(exit $fail); exit $fail

View File

@@ -33,8 +33,8 @@ output_mode_string=drwxr-x-wT
mkdir -m$set_mode_string $tmp || fail=1
test -d $tmp || fail=1
set -- `ls -ld $tmp`
case "$1" in
mode=`ls -ld $tmp|cut -b-10`
case "$mode" in
$output_mode_string) ;;
*) fail=1 ;;
esac
@@ -49,8 +49,8 @@ mkdir -m$set_mode_string $tmp2 2> /dev/null && fail=1
mkdir --parents -m$set_mode_string $tmp2 || fail=1
test -d $tmp2 || fail=1
set -- `ls -ld $tmp2`
case "$1" in
mode=`ls -ld $tmp2|cut -b-10`
case "$mode" in
$output_mode_string) ;;
*) fail=1 ;;
esac

View File

@@ -49,7 +49,7 @@ test -f file && fail=1
test -f $other_partition_tmpdir/file || fail=1
# This would have failed with the mv from fileutils-4.0i.
set _ `ls -l $other_partition_tmpdir/file`; shift; mode=$1
mode=`ls -l $other_partition_tmpdir/file|cut -b-10`
test "$mode" = "-rwxrwxrwx" || fail=1
exit $fail

24
tests/selinux Normal file
View File

@@ -0,0 +1,24 @@
# Is a test expensive?
# Copyright (C) 2007 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
test "`ls -Zd .`" = '? .' &&
{
echo "$0: skipping this test; this system (or maybe just" 1>&2
echo " the current file system) lacks SELinux support" 1>&2
(exit 77); exit 77
}