[Buildroot] [PATCH v2] makedevs: add capability support
Yann E. MORIN
yann.morin.1998 at free.fr
Thu Jun 16 17:10:37 UTC 2016
Philippe, All,
On 2016-06-16 12:59 +0200, Philippe Reynes spake thusly:
> Add the support of capability to makedevs as extended attribute.
> Now, it's possible to add a line "|xattr <capability>" after a
> file description to also add a capability to this file. It's
> possible to add severals capabilities with severals lines.
>
> Signed-off-by: Philippe Reynes <philippe.reynes at sagemcom.com>
> ---
> Changelog:
> v2:
> - add an option to enable (or not) xattr support in makedevs
> - update makedevs code to handle |xattr on the first line
> - add documentation about xattr support in makedevs
Thanks for this new version. See below for a few comments...
> docs/manual/makedev-syntax.txt | 28 ++++++++++++++
> package/makedevs/makedevs.c | 80 +++++++++++++++++++++++++++++++++++++++-
> package/makedevs/makedevs.mk | 10 ++++-
> system/Config.in | 5 +++
> 4 files changed, 119 insertions(+), 4 deletions(-)
>
> diff --git a/docs/manual/makedev-syntax.txt b/docs/manual/makedev-syntax.txt
> index e4dffc9..dd7bfdb 100644
> --- a/docs/manual/makedev-syntax.txt
> +++ b/docs/manual/makedev-syntax.txt
> @@ -71,3 +71,31 @@ and then for device files corresponding to the partitions of
> /dev/hda b 640 root root 3 1 1 1 15
> ----
>
> +The tool makedevs supports extended attributes for a file.
> +This is done by adding a line starting with +|xattr+ after
> +the line describing the file. Right now, only capability
> +is supported as extended attribute.
> +
> +|=====================
> +| \|xattr | capability
> +|=====================
> +
> +- +|xattr+ is a "flag" that indicate an extended attribute
> +- +capability+ is a capability to add to the previous file
> +
> +If you want to add the capability cap_sys_admin to the binary foo, you will write :
> +
> +----
> +/usr/bin/foo f 755 root root - - - - -
> +|xattr cap_sys_admin+eip
> +----
> +
> +You can add severals capabilities to a file by using severals +|xattr+ lines.
> +If you want to add the capability cap_sys_admin and cap_net_admin to the binary foo,
> +you will write :
> +
> +----
> +/usr/bin/foo f 755 root root - - - - -
> +|xattr cap_sys_admin+eip
> +|xattr cap_net_admin+eip
> +----
Good, thanks! :-)
Note: have you considered if it be possible that one could write multiple
xattrs on the same line, like:
/usr/bin/foo f 755 root root - - - - -
|xattr cap_sys_admin+eip cap_net_admin+eip
Note: I am *not* askign that you do that for a respin.
> diff --git a/package/makedevs/makedevs.c b/package/makedevs/makedevs.c
> index e5ef164..e2d084f 100644
> --- a/package/makedevs/makedevs.c
> +++ b/package/makedevs/makedevs.c
> @@ -35,6 +35,7 @@
> #include <sys/sysmacros.h> /* major() and minor() */
> #endif
> #include <ftw.h>
> +#include <sys/capability.h>
Minor comment is here: this include line should also be guarded with
#ifdef EXTENDED_ATTRIBUTES
> const char *bb_applet_name;
> uid_t recursive_uid;
> @@ -349,6 +350,57 @@ char *concat_path_file(const char *path, const char *filename)
> return outbuf;
> }
>
> +#ifdef EXTENDED_ATTRIBUTES
> +int bb_set_xattr(const char *fpath, const char *xattr)
> +{
> + cap_t cap, cap_file, cap_new;
> + char *cap_file_text, *cap_new_text;
> + ssize_t length;
> +
> + cap = cap_from_text(xattr);
> + if (cap == NULL) {
> + bb_perror_msg("cap_from_text failed for %s", xattr);
> + return -1;
> + }
> +
> + cap_file = cap_get_file(fpath);
> + if (cap_file == NULL) {
> + /* if no capability was set before, we initialize cap_file */
> + if (errno == ENODATA) {
My man page for cap_get_file() does not document ENODATA.
> + cap_file = cap_init();
What if cap_init() fails (it can return NULL on error)?
> + } else {
> + bb_perror_msg("cap_get_file failed on %s", fpath);
> + return -1;
> + }
> + }
> +
> + if ((cap_file_text = cap_to_text(cap_file, &length)) == NULL) {
> + bb_perror_msg("cap_to_name failed on %s", fpath);
> + return -1;
> + }
> +
> + bb_xasprintf(&cap_new_text, "%s %s", cap_file_text, xattr);
> +
> + if ((cap_new = cap_from_text(cap_new_text)) == NULL) {
> + bb_perror_msg("cap_from_text failed on %s", cap_new_text);
> + return -1;
> + }
> +
> + if (cap_set_file(fpath, cap_new) == -1) {
> + bb_perror_msg("cap_set_file failed for %s (xattr = %s)", fpath, xattr);
> + return -1;
> + }
> +
> + cap_free(cap);
> + cap_free(cap_file);
> + cap_free(cap_file_text);
> + cap_free(cap_new);
> + cap_free(cap_new_text);
Well, instead of all those "return -1" I think it would be much simpler
to just exit(1) right away.
Otherwise, none of the allocations done by the various cap_XXX()
functions would be freed. Granted, makedevs is not long-lived, but on a
very large target/ directory, with failures on a lot of files, this
could leak quite some memory in the end.
So, really, just exit(1) on error. We can't do much, so there's no point
in trying to continue: we won't be able to recover or fallback to
anything.
> + return 0;
> +}
> +#endif /* EXTENDED_ATTRIBUTES */
> +
> void bb_show_usage(void)
> {
> fprintf(stderr, "%s: [-d device_table] rootdir\n\n", bb_applet_name);
> @@ -413,6 +465,7 @@ int main(int argc, char **argv)
> int opt;
> FILE *table = stdin;
> char *rootdir = NULL;
> + char *full_name = NULL;
> char *line = NULL;
> int linenum = 0;
> int ret = EXIT_SUCCESS;
> @@ -454,15 +507,32 @@ int main(int argc, char **argv)
> unsigned int count = 0;
> unsigned int increment = 0;
> unsigned int start = 0;
> + char xattr[255];
> char name[4096];
> char user[41];
> char group[41];
> - char *full_name;
> uid_t uid;
> gid_t gid;
>
> linenum++;
>
> + if (1 == sscanf(line, "|xattr %254s", xattr))
> + {
> +#ifdef EXTENDED_ATTRIBUTES
> + if (!full_name) {
> + bb_error_msg("line %d should be after a file\n", linenum);
> + ret = EXIT_FAILURE;
Ditto, just exit().
> + } else {
> + if (bb_set_xattr(full_name, xattr) < 0)
> + ret = EXIT_FAILURE;
Ditto.
> + }
> +#else
> + bb_error_msg("line %d not supported: '%s'\n", linenum, line);
> + ret = EXIT_FAILURE;
Ditto.
Thanks! :-)
Regards,
Yann E. MORIN.
> +#endif /* EXTENDED_ATTRIBUTES */
> + continue;
> + }
> +
> if ((2 > sscanf(line, "%4095s %c %o %40s %40s %u %u %u %u %u", name,
> &type, &mode, user, group, &major,
> &minor, &start, &increment, &count)) ||
> @@ -487,6 +557,13 @@ int main(int argc, char **argv)
> } else {
> uid = getuid();
> }
> +
> + /*
> + * free previous full name
> + * we don't de-allocate full_name at the end of the parsing,
> + * because we may need it if the next line is an xattr.
> + */
> + free(full_name);
> full_name = concat_path_file(rootdir, name);
>
> if (type == 'd') {
> @@ -585,7 +662,6 @@ int main(int argc, char **argv)
> }
> loop:
> free(line);
> - free(full_name);
> }
> fclose(table);
>
> diff --git a/package/makedevs/makedevs.mk b/package/makedevs/makedevs.mk
> index fa8e753..b2efda9 100644
> --- a/package/makedevs/makedevs.mk
> +++ b/package/makedevs/makedevs.mk
> @@ -11,6 +11,12 @@ HOST_MAKEDEVS_SOURCE =
> MAKEDEVS_VERSION = buildroot-$(BR2_VERSION)
> MAKEDEVS_LICENSE = GPLv2
>
> +ifeq ($(BR2_ROOTFS_DEVICE_TABLE_SUPPORTS_EXTENDED_ATTRIBUTES),y)
> +HOST_MAKEDEVS_DEPENDENCIES += host-libcap
> +HOST_MAKEDEVS_CFLAGS = -DEXTENDED_ATTRIBUTES
> +HOST_MAKEDEVS_LDFLAGS = -lcap
> +endif
> +
> define MAKEDEVS_BUILD_CMDS
> $(TARGET_CC) $(TARGET_CFLAGS) $(TARGET_LDFLAGS) \
> package/makedevs/makedevs.c -o $(@D)/makedevs
> @@ -21,8 +27,8 @@ define MAKEDEVS_INSTALL_TARGET_CMDS
> endef
>
> define HOST_MAKEDEVS_BUILD_CMDS
> - $(HOSTCC) $(HOST_CFLAGS) $(HOST_LDFLAGS) \
> - package/makedevs/makedevs.c -o $(@D)/makedevs
> + $(HOSTCC) $(HOST_CFLAGS) $(HOST_LDFLAGS) $(HOST_MAKEDEVS_CFLAGS) \
> + package/makedevs/makedevs.c -o $(@D)/makedevs $(HOST_MAKEDEVS_LDFLAGS)
> endef
>
> define HOST_MAKEDEVS_INSTALL_CMDS
> diff --git a/system/Config.in b/system/Config.in
> index 9441467..a0ccc77 100644
> --- a/system/Config.in
> +++ b/system/Config.in
> @@ -162,6 +162,11 @@ config BR2_ROOTFS_STATIC_DEVICE_TABLE
> See package/makedevs/README for details on the usage and
> syntax of these files.
>
> +config BR2_ROOTFS_DEVICE_TABLE_SUPPORTS_EXTENDED_ATTRIBUTES
> + bool "device table supports extended attributes"
> + help
> + Add the support of extended attributes to device table
> +
> choice
> prompt "Root FS skeleton"
>
> --
> 1.7.9.5
>
>
> #
> " Ce courriel et les documents qui lui sont joints peuvent contenir des
> informations confidentielles ou ayant un caract?? priv??S'ils ne vous sont
> pas destin?? nous vous signalons qu'il est strictement interdit de les
> divulguer, de les reproduire ou d'en utiliser de quelque mani?? que ce
> soit le contenu. Si ce message vous a ?? transmis par erreur, merci d'en
> informer l'exp??teur et de supprimer imm??atement de votre syst??
> informatique ce courriel ainsi que tous les documents qui y sont attach??"
>
>
> ******
>
> " This e-mail and any attached documents may contain confidential or
> proprietary information. If you are not the intended recipient, you are
> notified that any dissemination, copying of this e-mail and any attachments
> thereto or use of their contents by any means whatsoever is strictly
> prohibited. If you have received this e-mail in error, please advise the
> sender immediately and delete this e-mail and all attached documents
> from your computer system."
> #
>
--
.-----------------.--------------------.------------------.--------------------.
| Yann E. MORIN | Real-Time Embedded | /"\ ASCII RIBBON | Erics' conspiracy: |
| +33 662 376 056 | Software Designer | \ / CAMPAIGN | ___ |
| +33 223 225 172 `------------.-------: X AGAINST | \e/ There is no |
| http://ymorin.is-a-geek.org/ | _/*\_ | / \ HTML MAIL | v conspiracy. |
'------------------------------^-------^------------------^--------------------'
More information about the buildroot
mailing list