apk: do not manage file ownership as non-root or when asked so
If apk is run as a non-root user, it's not possible to chown files. Maintainers note: minor wording changes on commit log and man page. Signed-off-by: Fredrik Gustafsson <fredrigu@axis.com>cute-signatures
parent
b67df9843d
commit
d61c009f7a
|
@ -39,6 +39,12 @@ following options:
|
||||||
virtual package, and by deleting that package the *apk add* operation
|
virtual package, and by deleting that package the *apk add* operation
|
||||||
may be easily reverted later.
|
may be easily reverted later.
|
||||||
|
|
||||||
|
*--no-chown*
|
||||||
|
Do not change file owner or group. By default apk will manage the file
|
||||||
|
ownership when running as root. However, this option is turned on when
|
||||||
|
running as non-root user, as changing file ownership is not permitted
|
||||||
|
by the system then.
|
||||||
|
|
||||||
# AUTHORS
|
# AUTHORS
|
||||||
|
|
||||||
Natanael Copa <ncopa@alpinelinux.org>++
|
Natanael Copa <ncopa@alpinelinux.org>++
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
#include "apk_blob.h"
|
#include "apk_blob.h"
|
||||||
#include "apk_io.h"
|
#include "apk_io.h"
|
||||||
|
|
||||||
|
#define APK_EXTRACTF_NO_CHOWN 0x0001
|
||||||
|
|
||||||
typedef int (*apk_archive_entry_parser)(void *ctx,
|
typedef int (*apk_archive_entry_parser)(void *ctx,
|
||||||
const struct apk_file_info *ae,
|
const struct apk_file_info *ae,
|
||||||
struct apk_istream *istream);
|
struct apk_istream *istream);
|
||||||
|
@ -30,6 +32,7 @@ int apk_tar_write_padding(struct apk_ostream *, const struct apk_file_info *ae);
|
||||||
int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae,
|
int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae,
|
||||||
const char *extract_name, const char *hardlink_name,
|
const char *extract_name, const char *hardlink_name,
|
||||||
struct apk_istream *is,
|
struct apk_istream *is,
|
||||||
apk_progress_cb cb, void *cb_ctx);
|
apk_progress_cb cb, void *cb_ctx,
|
||||||
|
unsigned int extract_flags);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -155,6 +155,7 @@ struct apk_database {
|
||||||
unsigned int local_repos, available_repos, cache_max_age;
|
unsigned int local_repos, available_repos, cache_max_age;
|
||||||
unsigned int repo_update_errors, repo_update_counter;
|
unsigned int repo_update_errors, repo_update_counter;
|
||||||
unsigned int pending_triggers;
|
unsigned int pending_triggers;
|
||||||
|
unsigned int extract_flags;
|
||||||
int performing_self_upgrade : 1;
|
int performing_self_upgrade : 1;
|
||||||
int permanent : 1;
|
int permanent : 1;
|
||||||
int autoupdate : 1;
|
int autoupdate : 1;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
struct add_ctx {
|
struct add_ctx {
|
||||||
const char *virtpkg;
|
const char *virtpkg;
|
||||||
unsigned short solver_flags;
|
unsigned short solver_flags;
|
||||||
|
unsigned short extract_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int optch, const char *optarg)
|
static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int optch, const char *optarg)
|
||||||
|
@ -30,6 +31,9 @@ static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt
|
||||||
case 0x10000:
|
case 0x10000:
|
||||||
dbopts->open_flags |= APK_OPENF_CREATE;
|
dbopts->open_flags |= APK_OPENF_CREATE;
|
||||||
break;
|
break;
|
||||||
|
case 0x10001:
|
||||||
|
actx->extract_flags |= APK_EXTRACTF_NO_CHOWN;
|
||||||
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
actx->solver_flags |= APK_SOLVERF_UPGRADE;
|
actx->solver_flags |= APK_SOLVERF_UPGRADE;
|
||||||
break;
|
break;
|
||||||
|
@ -47,6 +51,7 @@ static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int opt
|
||||||
|
|
||||||
static const struct apk_option options_applet[] = {
|
static const struct apk_option options_applet[] = {
|
||||||
{ 0x10000, "initdb" },
|
{ 0x10000, "initdb" },
|
||||||
|
{ 0x10001, "no-chown" },
|
||||||
{ 'u', "upgrade" },
|
{ 'u', "upgrade" },
|
||||||
{ 'l', "latest" },
|
{ 'l', "latest" },
|
||||||
{ 't', "virtual", required_argument, "NAME" },
|
{ 't', "virtual", required_argument, "NAME" },
|
||||||
|
@ -118,6 +123,9 @@ static int add_main(void *ctx, struct apk_database *db, struct apk_string_array
|
||||||
|
|
||||||
apk_dependency_array_copy(&world, db->world);
|
apk_dependency_array_copy(&world, db->world);
|
||||||
|
|
||||||
|
if (getuid() != 0 || (actx->extract_flags & APK_EXTRACTF_NO_CHOWN))
|
||||||
|
db->extract_flags |= APK_EXTRACTF_NO_CHOWN;
|
||||||
|
|
||||||
if (actx->virtpkg) {
|
if (actx->virtpkg) {
|
||||||
apk_blob_t b = APK_BLOB_STR(actx->virtpkg);
|
apk_blob_t b = APK_BLOB_STR(actx->virtpkg);
|
||||||
apk_blob_pull_dep(&b, db, &virtdep);
|
apk_blob_pull_dep(&b, db, &virtdep);
|
||||||
|
|
|
@ -1347,6 +1347,10 @@ static int apk_db_create(struct apk_database *db)
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
close(fd);
|
close(fd);
|
||||||
|
fd = openat(db->root_fd, apk_installed_file, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, 0644);
|
||||||
|
if (fd < 0)
|
||||||
|
return -errno;
|
||||||
|
close(fd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2554,7 +2558,7 @@ static int apk_db_install_archive_entry(void *_ctx,
|
||||||
db->root_fd, ae,
|
db->root_fd, ae,
|
||||||
format_tmpname(pkg, file, tmpname_file),
|
format_tmpname(pkg, file, tmpname_file),
|
||||||
format_tmpname(pkg, link_target_file, tmpname_link_target),
|
format_tmpname(pkg, link_target_file, tmpname_link_target),
|
||||||
is, extract_cb, ctx);
|
is, extract_cb, ctx, db->extract_flags);
|
||||||
|
|
||||||
switch (r) {
|
switch (r) {
|
||||||
case 0:
|
case 0:
|
||||||
|
|
|
@ -337,7 +337,8 @@ int apk_tar_write_padding(struct apk_ostream *os, const struct apk_file_info *ae
|
||||||
int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae,
|
int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae,
|
||||||
const char *extract_name, const char *link_target,
|
const char *extract_name, const char *link_target,
|
||||||
struct apk_istream *is,
|
struct apk_istream *is,
|
||||||
apk_progress_cb cb, void *cb_ctx)
|
apk_progress_cb cb, void *cb_ctx,
|
||||||
|
unsigned int apk_extract_flags)
|
||||||
{
|
{
|
||||||
struct apk_xattr *xattr;
|
struct apk_xattr *xattr;
|
||||||
const char *fn = extract_name ?: ae->name;
|
const char *fn = extract_name ?: ae->name;
|
||||||
|
@ -385,22 +386,24 @@ int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = fchownat(atfd, fn, ae->uid, ae->gid, atflags);
|
if (!(apk_extract_flags & APK_EXTRACTF_NO_CHOWN)) {
|
||||||
if (r < 0) {
|
r = fchownat(atfd, fn, ae->uid, ae->gid, atflags);
|
||||||
apk_error("Failed to set ownership on %s: %s",
|
|
||||||
fn, strerror(errno));
|
|
||||||
if (!ret) ret = -errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* chown resets suid bit so we need set it again */
|
|
||||||
if (ae->mode & 07000) {
|
|
||||||
r = fchmodat(atfd, fn, ae->mode & 07777, atflags);
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
apk_error("Failed to set file permissions "
|
apk_error("Failed to set ownership on %s: %s",
|
||||||
"on %s: %s",
|
|
||||||
fn, strerror(errno));
|
fn, strerror(errno));
|
||||||
if (!ret) ret = -errno;
|
if (!ret) ret = -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* chown resets suid bit so we need set it again */
|
||||||
|
if (ae->mode & 07000) {
|
||||||
|
r = fchmodat(atfd, fn, ae->mode & 07777, atflags);
|
||||||
|
if (r < 0) {
|
||||||
|
apk_error("Failed to set file permissions "
|
||||||
|
"on %s: %s",
|
||||||
|
fn, strerror(errno));
|
||||||
|
if (!ret) ret = -errno;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* extract xattrs */
|
/* extract xattrs */
|
||||||
|
|
Loading…
Reference in New Issue