Merge branch 'mm/mkstemps-mode-for-packfiles'
* mm/mkstemps-mode-for-packfiles: Use git_mkstemp_mode instead of plain mkstemp to create object files git_mkstemps_mode: don't set errno to EINVAL on exit. Use git_mkstemp_mode and xmkstemp_mode in odb_mkstemp, not chmod later. git_mkstemp_mode, xmkstemp_mode: variants of gitmkstemps with mode argument. Move gitmkstemps to path.c Add a testcase for ACL with restrictive umask.
This commit is contained in:
commit
87912fd617
1
Makefile
1
Makefile
@ -1241,7 +1241,6 @@ ifdef NO_MKDTEMP
|
|||||||
endif
|
endif
|
||||||
ifdef NO_MKSTEMPS
|
ifdef NO_MKSTEMPS
|
||||||
COMPAT_CFLAGS += -DNO_MKSTEMPS
|
COMPAT_CFLAGS += -DNO_MKSTEMPS
|
||||||
COMPAT_OBJS += compat/mkstemps.o
|
|
||||||
endif
|
endif
|
||||||
ifdef NO_UNSETENV
|
ifdef NO_UNSETENV
|
||||||
COMPAT_CFLAGS += -DNO_UNSETENV
|
COMPAT_CFLAGS += -DNO_UNSETENV
|
||||||
|
@ -437,9 +437,6 @@ static int write_one(struct sha1file *f,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* forward declaration for write_pack_file */
|
|
||||||
static int adjust_perm(const char *path, mode_t mode);
|
|
||||||
|
|
||||||
static void write_pack_file(void)
|
static void write_pack_file(void)
|
||||||
{
|
{
|
||||||
uint32_t i = 0, j;
|
uint32_t i = 0, j;
|
||||||
@ -496,21 +493,17 @@ static void write_pack_file(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!pack_to_stdout) {
|
if (!pack_to_stdout) {
|
||||||
mode_t mode = umask(0);
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
const char *idx_tmp_name;
|
const char *idx_tmp_name;
|
||||||
char tmpname[PATH_MAX];
|
char tmpname[PATH_MAX];
|
||||||
|
|
||||||
umask(mode);
|
|
||||||
mode = 0444 & ~mode;
|
|
||||||
|
|
||||||
idx_tmp_name = write_idx_file(NULL, written_list,
|
idx_tmp_name = write_idx_file(NULL, written_list,
|
||||||
nr_written, sha1);
|
nr_written, sha1);
|
||||||
|
|
||||||
snprintf(tmpname, sizeof(tmpname), "%s-%s.pack",
|
snprintf(tmpname, sizeof(tmpname), "%s-%s.pack",
|
||||||
base_name, sha1_to_hex(sha1));
|
base_name, sha1_to_hex(sha1));
|
||||||
free_pack_by_name(tmpname);
|
free_pack_by_name(tmpname);
|
||||||
if (adjust_perm(pack_tmp_name, mode))
|
if (adjust_shared_perm(pack_tmp_name))
|
||||||
die_errno("unable to make temporary pack file readable");
|
die_errno("unable to make temporary pack file readable");
|
||||||
if (rename(pack_tmp_name, tmpname))
|
if (rename(pack_tmp_name, tmpname))
|
||||||
die_errno("unable to rename temporary pack file");
|
die_errno("unable to rename temporary pack file");
|
||||||
@ -538,7 +531,7 @@ static void write_pack_file(void)
|
|||||||
|
|
||||||
snprintf(tmpname, sizeof(tmpname), "%s-%s.idx",
|
snprintf(tmpname, sizeof(tmpname), "%s-%s.idx",
|
||||||
base_name, sha1_to_hex(sha1));
|
base_name, sha1_to_hex(sha1));
|
||||||
if (adjust_perm(idx_tmp_name, mode))
|
if (adjust_shared_perm(idx_tmp_name))
|
||||||
die_errno("unable to make temporary index file readable");
|
die_errno("unable to make temporary index file readable");
|
||||||
if (rename(idx_tmp_name, tmpname))
|
if (rename(idx_tmp_name, tmpname))
|
||||||
die_errno("unable to rename temporary index file");
|
die_errno("unable to rename temporary index file");
|
||||||
@ -2098,13 +2091,6 @@ static void get_object_list(int ac, const char **av)
|
|||||||
loosen_unused_packed_objects(&revs);
|
loosen_unused_packed_objects(&revs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int adjust_perm(const char *path, mode_t mode)
|
|
||||||
{
|
|
||||||
if (chmod(path, mode))
|
|
||||||
return -1;
|
|
||||||
return adjust_shared_perm(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
int cmd_pack_objects(int argc, const char **argv, const char *prefix)
|
int cmd_pack_objects(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int use_internal_rev_list = 0;
|
int use_internal_rev_list = 0;
|
||||||
|
4
cache.h
4
cache.h
@ -641,6 +641,10 @@ int git_mkstemp(char *path, size_t n, const char *template);
|
|||||||
|
|
||||||
int git_mkstemps(char *path, size_t n, const char *template, int suffix_len);
|
int git_mkstemps(char *path, size_t n, const char *template, int suffix_len);
|
||||||
|
|
||||||
|
/* set default permissions by passing mode arguments to open(2) */
|
||||||
|
int git_mkstemps_mode(char *pattern, int suffix_len, int mode);
|
||||||
|
int git_mkstemp_mode(char *pattern, int mode);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE NOTE NOTE!!
|
* NOTE NOTE NOTE!!
|
||||||
*
|
*
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
#include "../git-compat-util.h"
|
|
||||||
|
|
||||||
/* Adapted from libiberty's mkstemp.c. */
|
|
||||||
|
|
||||||
#undef TMP_MAX
|
|
||||||
#define TMP_MAX 16384
|
|
||||||
|
|
||||||
int gitmkstemps(char *pattern, int suffix_len)
|
|
||||||
{
|
|
||||||
static const char letters[] =
|
|
||||||
"abcdefghijklmnopqrstuvwxyz"
|
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
||||||
"0123456789";
|
|
||||||
static const int num_letters = 62;
|
|
||||||
uint64_t value;
|
|
||||||
struct timeval tv;
|
|
||||||
char *template;
|
|
||||||
size_t len;
|
|
||||||
int fd, count;
|
|
||||||
|
|
||||||
len = strlen(pattern);
|
|
||||||
|
|
||||||
if (len < 6 + suffix_len) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strncmp(&pattern[len - 6 - suffix_len], "XXXXXX", 6)) {
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Replace pattern's XXXXXX characters with randomness.
|
|
||||||
* Try TMP_MAX different filenames.
|
|
||||||
*/
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
value = ((size_t)(tv.tv_usec << 16)) ^ tv.tv_sec ^ getpid();
|
|
||||||
template = &pattern[len - 6 - suffix_len];
|
|
||||||
for (count = 0; count < TMP_MAX; ++count) {
|
|
||||||
uint64_t v = value;
|
|
||||||
/* Fill in the random bits. */
|
|
||||||
template[0] = letters[v % num_letters]; v /= num_letters;
|
|
||||||
template[1] = letters[v % num_letters]; v /= num_letters;
|
|
||||||
template[2] = letters[v % num_letters]; v /= num_letters;
|
|
||||||
template[3] = letters[v % num_letters]; v /= num_letters;
|
|
||||||
template[4] = letters[v % num_letters]; v /= num_letters;
|
|
||||||
template[5] = letters[v % num_letters]; v /= num_letters;
|
|
||||||
|
|
||||||
fd = open(pattern, O_CREAT | O_EXCL | O_RDWR, 0600);
|
|
||||||
if (fd > 0)
|
|
||||||
return fd;
|
|
||||||
/*
|
|
||||||
* Fatal error (EPERM, ENOSPC etc).
|
|
||||||
* It doesn't make sense to loop.
|
|
||||||
*/
|
|
||||||
if (errno != EEXIST)
|
|
||||||
break;
|
|
||||||
/*
|
|
||||||
* This is a random value. It is only necessary that
|
|
||||||
* the next TMP_MAX values generated by adding 7777 to
|
|
||||||
* VALUE are different with (module 2^32).
|
|
||||||
*/
|
|
||||||
value += 7777;
|
|
||||||
}
|
|
||||||
/* We return the null string if we can't find a unique file name. */
|
|
||||||
pattern[0] = '\0';
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
79
path.c
79
path.c
@ -157,6 +157,85 @@ int git_mkstemps(char *path, size_t len, const char *template, int suffix_len)
|
|||||||
return mkstemps(path, suffix_len);
|
return mkstemps(path, suffix_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Adapted from libiberty's mkstemp.c. */
|
||||||
|
|
||||||
|
#undef TMP_MAX
|
||||||
|
#define TMP_MAX 16384
|
||||||
|
|
||||||
|
int git_mkstemps_mode(char *pattern, int suffix_len, int mode)
|
||||||
|
{
|
||||||
|
static const char letters[] =
|
||||||
|
"abcdefghijklmnopqrstuvwxyz"
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
"0123456789";
|
||||||
|
static const int num_letters = 62;
|
||||||
|
uint64_t value;
|
||||||
|
struct timeval tv;
|
||||||
|
char *template;
|
||||||
|
size_t len;
|
||||||
|
int fd, count;
|
||||||
|
|
||||||
|
len = strlen(pattern);
|
||||||
|
|
||||||
|
if (len < 6 + suffix_len) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncmp(&pattern[len - 6 - suffix_len], "XXXXXX", 6)) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Replace pattern's XXXXXX characters with randomness.
|
||||||
|
* Try TMP_MAX different filenames.
|
||||||
|
*/
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
value = ((size_t)(tv.tv_usec << 16)) ^ tv.tv_sec ^ getpid();
|
||||||
|
template = &pattern[len - 6 - suffix_len];
|
||||||
|
for (count = 0; count < TMP_MAX; ++count) {
|
||||||
|
uint64_t v = value;
|
||||||
|
/* Fill in the random bits. */
|
||||||
|
template[0] = letters[v % num_letters]; v /= num_letters;
|
||||||
|
template[1] = letters[v % num_letters]; v /= num_letters;
|
||||||
|
template[2] = letters[v % num_letters]; v /= num_letters;
|
||||||
|
template[3] = letters[v % num_letters]; v /= num_letters;
|
||||||
|
template[4] = letters[v % num_letters]; v /= num_letters;
|
||||||
|
template[5] = letters[v % num_letters]; v /= num_letters;
|
||||||
|
|
||||||
|
fd = open(pattern, O_CREAT | O_EXCL | O_RDWR, mode);
|
||||||
|
if (fd > 0)
|
||||||
|
return fd;
|
||||||
|
/*
|
||||||
|
* Fatal error (EPERM, ENOSPC etc).
|
||||||
|
* It doesn't make sense to loop.
|
||||||
|
*/
|
||||||
|
if (errno != EEXIST)
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
* This is a random value. It is only necessary that
|
||||||
|
* the next TMP_MAX values generated by adding 7777 to
|
||||||
|
* VALUE are different with (module 2^32).
|
||||||
|
*/
|
||||||
|
value += 7777;
|
||||||
|
}
|
||||||
|
/* We return the null string if we can't find a unique file name. */
|
||||||
|
pattern[0] = '\0';
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_mkstemp_mode(char *pattern, int mode)
|
||||||
|
{
|
||||||
|
/* mkstemp is just mkstemps with no suffix */
|
||||||
|
return git_mkstemps_mode(pattern, 0, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
int gitmkstemps(char *pattern, int suffix_len)
|
||||||
|
{
|
||||||
|
return git_mkstemps_mode(pattern, suffix_len, 0600);
|
||||||
|
}
|
||||||
|
|
||||||
int validate_headref(const char *path)
|
int validate_headref(const char *path)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
@ -2206,7 +2206,7 @@ int move_temp_to_file(const char *tmpfile, const char *filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (set_shared_perm(filename, (S_IFREG|0444)))
|
if (adjust_shared_perm(filename))
|
||||||
return error("unable to set permission to '%s'", filename);
|
return error("unable to set permission to '%s'", filename);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2262,7 +2262,7 @@ static int create_tmpfile(char *buffer, size_t bufsiz, const char *filename)
|
|||||||
}
|
}
|
||||||
memcpy(buffer, filename, dirlen);
|
memcpy(buffer, filename, dirlen);
|
||||||
strcpy(buffer + dirlen, "tmp_obj_XXXXXX");
|
strcpy(buffer + dirlen, "tmp_obj_XXXXXX");
|
||||||
fd = mkstemp(buffer);
|
fd = git_mkstemp_mode(buffer, 0444);
|
||||||
if (fd < 0 && dirlen && errno == ENOENT) {
|
if (fd < 0 && dirlen && errno == ENOENT) {
|
||||||
/* Make sure the directory exists */
|
/* Make sure the directory exists */
|
||||||
memcpy(buffer, filename, dirlen);
|
memcpy(buffer, filename, dirlen);
|
||||||
@ -2272,7 +2272,7 @@ static int create_tmpfile(char *buffer, size_t bufsiz, const char *filename)
|
|||||||
|
|
||||||
/* Try again */
|
/* Try again */
|
||||||
strcpy(buffer + dirlen - 1, "/tmp_obj_XXXXXX");
|
strcpy(buffer + dirlen - 1, "/tmp_obj_XXXXXX");
|
||||||
fd = mkstemp(buffer);
|
fd = git_mkstemp_mode(buffer, 0444);
|
||||||
}
|
}
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
67
t/t1304-default-acl.sh
Executable file
67
t/t1304-default-acl.sh
Executable file
@ -0,0 +1,67 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Copyright (c) 2010 Matthieu Moy
|
||||||
|
#
|
||||||
|
|
||||||
|
test_description='Test repository with default ACL'
|
||||||
|
|
||||||
|
# Create the test repo with restrictive umask
|
||||||
|
# => this must come before . ./test-lib.sh
|
||||||
|
umask 077
|
||||||
|
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
# We need an arbitrary other user give permission to using ACLs. root
|
||||||
|
# is a good candidate: exists on all unices, and it has permission
|
||||||
|
# anyway, so we don't create a security hole running the testsuite.
|
||||||
|
|
||||||
|
if ! setfacl -m u:root:rwx .; then
|
||||||
|
say "Skipping ACL tests: unable to use setfacl"
|
||||||
|
test_done
|
||||||
|
fi
|
||||||
|
|
||||||
|
modebits () {
|
||||||
|
ls -l "$1" | sed -e 's|^\(..........\).*|\1|'
|
||||||
|
}
|
||||||
|
|
||||||
|
check_perms_and_acl () {
|
||||||
|
actual=$(modebits "$1") &&
|
||||||
|
case "$actual" in
|
||||||
|
-r--r-----*)
|
||||||
|
: happy
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Got permission '$actual', expected '-r--r-----'"
|
||||||
|
false
|
||||||
|
;;
|
||||||
|
esac &&
|
||||||
|
getfacl "$1" > actual &&
|
||||||
|
grep -q "user:root:rwx" actual &&
|
||||||
|
grep -q "user:${LOGNAME}:rwx" actual &&
|
||||||
|
grep -q "mask::r--" actual &&
|
||||||
|
grep -q "group::---" actual || false
|
||||||
|
}
|
||||||
|
|
||||||
|
dirs_to_set="./ .git/ .git/objects/ .git/objects/pack/"
|
||||||
|
|
||||||
|
test_expect_success 'Setup test repo' '
|
||||||
|
setfacl -m u:root:rwx $dirs_to_set &&
|
||||||
|
setfacl -d -m u:"$LOGNAME":rwx $dirs_to_set &&
|
||||||
|
setfacl -d -m u:root:rwx $dirs_to_set &&
|
||||||
|
|
||||||
|
touch file.txt &&
|
||||||
|
git add file.txt &&
|
||||||
|
git commit -m "init"
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'Objects creation does not break ACLs with restrictive umask' '
|
||||||
|
# SHA1 for empty blob
|
||||||
|
check_perms_and_acl .git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'git gc does not break ACLs with restrictive umask' '
|
||||||
|
git gc &&
|
||||||
|
check_perms_and_acl .git/objects/pack/*.pack
|
||||||
|
'
|
||||||
|
|
||||||
|
test_done
|
20
wrapper.c
20
wrapper.c
@ -204,6 +204,16 @@ int xmkstemp(char *template)
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int xmkstemp_mode(char *template, int mode)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = git_mkstemp_mode(template, mode);
|
||||||
|
if (fd < 0)
|
||||||
|
die_errno("Unable to create temporary file");
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* zlib wrappers to make sure we don't silently miss errors
|
* zlib wrappers to make sure we don't silently miss errors
|
||||||
* at init time.
|
* at init time.
|
||||||
@ -267,10 +277,14 @@ int git_inflate(z_streamp strm, int flush)
|
|||||||
int odb_mkstemp(char *template, size_t limit, const char *pattern)
|
int odb_mkstemp(char *template, size_t limit, const char *pattern)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
/*
|
||||||
|
* we let the umask do its job, don't try to be more
|
||||||
|
* restrictive except to remove write permission.
|
||||||
|
*/
|
||||||
|
int mode = 0444;
|
||||||
snprintf(template, limit, "%s/%s",
|
snprintf(template, limit, "%s/%s",
|
||||||
get_object_directory(), pattern);
|
get_object_directory(), pattern);
|
||||||
fd = mkstemp(template);
|
fd = git_mkstemp_mode(template, mode);
|
||||||
if (0 <= fd)
|
if (0 <= fd)
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
@ -279,7 +293,7 @@ int odb_mkstemp(char *template, size_t limit, const char *pattern)
|
|||||||
snprintf(template, limit, "%s/%s",
|
snprintf(template, limit, "%s/%s",
|
||||||
get_object_directory(), pattern);
|
get_object_directory(), pattern);
|
||||||
safe_create_leading_directories(template);
|
safe_create_leading_directories(template);
|
||||||
return xmkstemp(template);
|
return xmkstemp_mode(template, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
int odb_pack_keep(char *name, size_t namesz, unsigned char *sha1)
|
int odb_pack_keep(char *name, size_t namesz, unsigned char *sha1)
|
||||||
|
Loading…
Reference in New Issue
Block a user