Do not chown downloads when DownloadUser is unset

On NFS caches, using chown to change file permissions to the UID 0 user
will fail due to root_squash.  When DownloadUser is unset, or set to
the UID 0 user (root), avoid the unneeded chown calls providing a
workaround.

Fixes #194

Signed-off-by: Allan McRae <allan@archlinux.org>
This commit is contained in:
Allan McRae 2025-05-08 23:00:57 +10:00
parent 692f7a2cfe
commit a60bbf1a45

View file

@ -73,17 +73,21 @@ static mode_t _getumask(void)
return mask; return mask;
} }
static int finalize_download_file(const char *filename) static int finalize_download_file(const char *filename, const char *user)
{ {
struct stat st; struct stat st;
uid_t myuid = getuid(); uid_t myuid = getuid();
struct passwd const *pw = NULL;
ASSERT(filename != NULL, return -1); ASSERT(filename != NULL, return -1);
ASSERT(stat(filename, &st) == 0, return -1); ASSERT(stat(filename, &st) == 0, return -1);
ASSERT((pw = getpwuid(0)) != NULL, return -1);
if(st.st_size == 0) { if(st.st_size == 0) {
unlink(filename); unlink(filename);
return 1; return 1;
} }
if(myuid == 0) { if(myuid == 0 && strcmp(user, pw->pw_name) != 0) {
ASSERT(chown(filename, 0, 0) != -1, return -1); ASSERT(chown(filename, 0, 0) != -1, return -1);
} }
ASSERT(chmod(filename, ~(_getumask()) & 0666) != -1, return -1); ASSERT(chmod(filename, ~(_getumask()) & 0666) != -1, return -1);
@ -1080,11 +1084,11 @@ static int payload_download_fetchcb(struct dload_payload *payload,
return ret; return ret;
} }
static int move_file(const char *filepath, const char *directory) static int move_file(const char *filepath, const char *directory, const char *user)
{ {
ASSERT(filepath != NULL, return -1); ASSERT(filepath != NULL, return -1);
ASSERT(directory != NULL, return -1); ASSERT(directory != NULL, return -1);
int ret = finalize_download_file(filepath); int ret = finalize_download_file(filepath, user);
if(ret != 0) { if(ret != 0) {
return ret; return ret;
} }
@ -1098,7 +1102,7 @@ static int move_file(const char *filepath, const char *directory)
return 0; return 0;
} }
static int finalize_download_locations(alpm_list_t *payloads, const char *localpath) static int finalize_download_locations(alpm_list_t *payloads, const char *localpath, const char *user)
{ {
ASSERT(payloads != NULL, return -1); ASSERT(payloads != NULL, return -1);
ASSERT(localpath != NULL, return -1); ASSERT(localpath != NULL, return -1);
@ -1107,10 +1111,10 @@ static int finalize_download_locations(alpm_list_t *payloads, const char *localp
for(p = payloads; p; p = p->next) { for(p = payloads; p; p = p->next) {
struct dload_payload *payload = p->data; struct dload_payload *payload = p->data;
if(payload->tempfile_name) { if(payload->tempfile_name) {
move_file(payload->tempfile_name, localpath); move_file(payload->tempfile_name, localpath, user);
} }
if(payload->destfile_name) { if(payload->destfile_name) {
int ret = move_file(payload->destfile_name, localpath); int ret = move_file(payload->destfile_name, localpath, user);
if(ret == -1) { if(ret == -1) {
/* ignore error if the file already existed - only signature file was downloaded */ /* ignore error if the file already existed - only signature file was downloaded */
@ -1127,7 +1131,7 @@ static int finalize_download_locations(alpm_list_t *payloads, const char *localp
size_t sig_filename_len = strlen(payload->destfile_name) + sizeof(sig_suffix); size_t sig_filename_len = strlen(payload->destfile_name) + sizeof(sig_suffix);
MALLOC(sig_filename, sig_filename_len, continue); MALLOC(sig_filename, sig_filename_len, continue);
snprintf(sig_filename, sig_filename_len, "%s%s", payload->destfile_name, sig_suffix); snprintf(sig_filename, sig_filename_len, "%s%s", payload->destfile_name, sig_suffix);
move_file(sig_filename, localpath); move_file(sig_filename, localpath, user);
FREE(sig_filename); FREE(sig_filename);
} }
} }
@ -1170,7 +1174,7 @@ static void prepare_resumable_downloads(alpm_list_t *payloads, const char *local
FREE(src); FREE(src);
continue; continue;
} }
if(pw != NULL) { if(pw != NULL && pw->pw_uid != 0) {
ASSERT(chown(payload->tempfile_name, pw->pw_uid, pw->pw_gid), return); ASSERT(chown(payload->tempfile_name, pw->pw_uid, pw->pw_gid), return);
} }
FREE(src); FREE(src);
@ -1267,7 +1271,7 @@ download_signature:
ret = updated ? 0 : 1; ret = updated ? 0 : 1;
} }
if (finalize_download_locations(payloads, localpath) != 0 && ret == 0) { if (finalize_download_locations(payloads, localpath, handle->sandboxuser) != 0 && ret == 0) {
RET_ERR(handle, ALPM_ERR_RETRIEVE, -1); RET_ERR(handle, ALPM_ERR_RETRIEVE, -1);
} }
return ret; return ret;