config: preserve config file permissions on edits
Users may already store sensitive data such as imap.pass in .git/config; making the file world-readable when "git config" is called to edit means their password would be compromised on a shared system. [v2: updated for section renames, as noted by Junio] Signed-off-by: Eric Wong <normalperson@yhbt.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Eric Wong committed
May 6, 2014 at 00:17 UTC
daa22c6f8da466bd7a438f1bc27375fd737ffcf3
2 files changed
+26
config.c
+16
@@ -1634,6 +1634,13 @@ int git_config_set_multivar_in_file(const char *config_filename,
1634
MAP_PRIVATE, in_fd, 0);
1635
close(in_fd);
1636
1637
+ if (fchmod(fd, st.st_mode & 07777) < 0) {
1638
+ error("fchmod on %s failed: %s",
1639
+ lock->filename, strerror(errno));
1640
+ ret = CONFIG_NO_WRITE;
1641
+ goto out_free;
1642
+ }
1643
+
1644
if (store.seen == 0)
1645
store.seen = 1;
1646
@@ -1782,6 +1789,7 @@ int git_config_rename_section_in_file(const char *config_filename,
1789
int out_fd;
1790
char buf[1024];
1791
FILE *config_file;
1792
+ struct stat st;
1793
1794
if (new_name && !section_name_is_ok(new_name)) {
1795
ret = error("invalid section name: %s", new_name);
@@ -1803,6 +1811,14 @@ int git_config_rename_section_in_file(const char *config_filename,
1811
goto unlock_and_out;
1812
}
1813
1814
+ fstat(fileno(config_file), &st);
1815
+
1816
+ if (fchmod(out_fd, st.st_mode & 07777) < 0) {
1817
+ ret = error("fchmod on %s failed: %s",
1818
+ lock->filename, strerror(errno));
1819
+ goto out;
1820
+ }
1821
+
1822
while (fgets(buf, sizeof(buf), config_file)) {
1823
int i;
1824
int length;
t/t1300-repo-config.sh
+10
@@ -1154,4 +1154,14 @@ test_expect_failure 'adding a key into an empty section reuses header' '
1154
test_cmp expect .git/config
1155
'
1156
1157
+test_expect_success POSIXPERM,PERL 'preserves existing permissions' '
1158
+ chmod 0600 .git/config &&
1159
+ git config imap.pass Hunter2 &&
1160
+ perl -e \
1161
+ "die q(badset) if ((stat(q(.git/config)))[2] & 07777) != 0600" &&
1162
+ git config --rename-section imap pop &&
1163
+ perl -e \
1164
+ "die q(badrename) if ((stat(q(.git/config)))[2] & 07777) != 0600"
1165
+'
1166
+
1167
test_done