Browse Source

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.
maint
Junio C Hamano 15 years ago
parent
commit
87912fd617
  1. 1
      Makefile
  2. 18
      builtin-pack-objects.c
  3. 4
      cache.h
  4. 70
      compat/mkstemps.c
  5. 79
      path.c
  6. 6
      sha1_file.c
  7. 67
      t/t1304-default-acl.sh
  8. 20
      wrapper.c

1
Makefile

@ -1241,7 +1241,6 @@ ifdef NO_MKDTEMP @@ -1241,7 +1241,6 @@ ifdef NO_MKDTEMP
endif
ifdef NO_MKSTEMPS
COMPAT_CFLAGS += -DNO_MKSTEMPS
COMPAT_OBJS += compat/mkstemps.o
endif
ifdef NO_UNSETENV
COMPAT_CFLAGS += -DNO_UNSETENV

18
builtin-pack-objects.c

@ -437,9 +437,6 @@ static int write_one(struct sha1file *f, @@ -437,9 +437,6 @@ static int write_one(struct sha1file *f,
return 1;
}

/* forward declaration for write_pack_file */
static int adjust_perm(const char *path, mode_t mode);

static void write_pack_file(void)
{
uint32_t i = 0, j;
@ -496,21 +493,17 @@ static void write_pack_file(void) @@ -496,21 +493,17 @@ static void write_pack_file(void)
}

if (!pack_to_stdout) {
mode_t mode = umask(0);
struct stat st;
const char *idx_tmp_name;
char tmpname[PATH_MAX];

umask(mode);
mode = 0444 & ~mode;

idx_tmp_name = write_idx_file(NULL, written_list,
nr_written, sha1);

snprintf(tmpname, sizeof(tmpname), "%s-%s.pack",
base_name, sha1_to_hex(sha1));
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");
if (rename(pack_tmp_name, tmpname))
die_errno("unable to rename temporary pack file");
@ -538,7 +531,7 @@ static void write_pack_file(void) @@ -538,7 +531,7 @@ static void write_pack_file(void)

snprintf(tmpname, sizeof(tmpname), "%s-%s.idx",
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");
if (rename(idx_tmp_name, tmpname))
die_errno("unable to rename temporary index file");
@ -2098,13 +2091,6 @@ static void get_object_list(int ac, const char **av) @@ -2098,13 +2091,6 @@ static void get_object_list(int ac, const char **av)
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 use_internal_rev_list = 0;

4
cache.h

@ -641,6 +641,10 @@ int git_mkstemp(char *path, size_t n, const char *template); @@ -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);

/* 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!!
*

70
compat/mkstemps.c

@ -1,70 +0,0 @@ @@ -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

@ -157,6 +157,85 @@ int git_mkstemps(char *path, size_t len, const char *template, int suffix_len) @@ -157,6 +157,85 @@ int git_mkstemps(char *path, size_t len, const char *template, int 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)
{
struct stat st;

6
sha1_file.c

@ -2206,7 +2206,7 @@ int move_temp_to_file(const char *tmpfile, const char *filename) @@ -2206,7 +2206,7 @@ int move_temp_to_file(const char *tmpfile, const char *filename)
}

out:
if (set_shared_perm(filename, (S_IFREG|0444)))
if (adjust_shared_perm(filename))
return error("unable to set permission to '%s'", filename);
return 0;
}
@ -2262,7 +2262,7 @@ static int create_tmpfile(char *buffer, size_t bufsiz, const char *filename) @@ -2262,7 +2262,7 @@ static int create_tmpfile(char *buffer, size_t bufsiz, const char *filename)
}
memcpy(buffer, filename, dirlen);
strcpy(buffer + dirlen, "tmp_obj_XXXXXX");
fd = mkstemp(buffer);
fd = git_mkstemp_mode(buffer, 0444);
if (fd < 0 && dirlen && errno == ENOENT) {
/* Make sure the directory exists */
memcpy(buffer, filename, dirlen);
@ -2272,7 +2272,7 @@ static int create_tmpfile(char *buffer, size_t bufsiz, const char *filename) @@ -2272,7 +2272,7 @@ static int create_tmpfile(char *buffer, size_t bufsiz, const char *filename)

/* Try again */
strcpy(buffer + dirlen - 1, "/tmp_obj_XXXXXX");
fd = mkstemp(buffer);
fd = git_mkstemp_mode(buffer, 0444);
}
return fd;
}

67
t/t1304-default-acl.sh

@ -0,0 +1,67 @@ @@ -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

@ -204,6 +204,16 @@ int xmkstemp(char *template) @@ -204,6 +204,16 @@ int xmkstemp(char *template)
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
* at init time.
@ -267,10 +277,14 @@ int git_inflate(z_streamp strm, int flush) @@ -267,10 +277,14 @@ int git_inflate(z_streamp strm, int flush)
int odb_mkstemp(char *template, size_t limit, const char *pattern)
{
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",
get_object_directory(), pattern);
fd = mkstemp(template);
fd = git_mkstemp_mode(template, mode);
if (0 <= fd)
return fd;

@ -279,7 +293,7 @@ int odb_mkstemp(char *template, size_t limit, const char *pattern) @@ -279,7 +293,7 @@ int odb_mkstemp(char *template, size_t limit, const char *pattern)
snprintf(template, limit, "%s/%s",
get_object_directory(), pattern);
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)

Loading…
Cancel
Save