Subject: Re: [PATCH v2 2/2] read-cache: make sure file handles are not inherited by child processes

From: Junio C Hamano <[email-masked]>
Date: Mon, 24 Oct 2016 12:53:10 -0700

Eric Wong <[email-masked]> writes:

> [email-masked] wrote:
>> +++ b/read-cache.c
>> @@ -156,7 +156,11 @@ void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
>>  static int ce_compare_data(const struct cache_entry *ce, struct stat *st)
>>  {
>>  	int match = -1;
>> -	int fd = open(ce->name, O_RDONLY);
>> +	int fd = open(ce->name, O_RDONLY | O_CLOEXEC);
>> +
>> +	if (O_CLOEXEC && fd < 0 && errno == EINVAL)
>> +		/* Try again w/o O_CLOEXEC: the kernel might not support it */
>> +		fd = open(ce->name, O_RDONLY);
>
> In the case of O_CLOEXEC != 0 and repeated EINVALs,
> it'd be good to use something like sha1_file_open_flag as in 1/2
> so we don't repeatedly hit EINVAL.  Thanks.

Sounds sane.  

It's just only once, so perhaps we do not mind a recursion like
this?

 read-cache.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/read-cache.c b/read-cache.c
index b594865d89..a6978b9321 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -156,11 +156,14 @@ void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
 static int ce_compare_data(const struct cache_entry *ce, struct stat *st)
 {
 	int match = -1;
-	int fd = open(ce->name, O_RDONLY | O_CLOEXEC);
+	static int cloexec = O_CLOEXEC;
+	int fd = open(ce->name, O_RDONLY | cloexec);
 
-	if (O_CLOEXEC && fd < 0 && errno == EINVAL)
+	if ((cloexec & O_CLOEXEC) && fd < 0 && errno == EINVAL) {
 		/* Try again w/o O_CLOEXEC: the kernel might not support it */
-		fd = open(ce->name, O_RDONLY);
+		cloexec &= ~O_CLOEXEC;
+		return ce_compare_data(ce, st);
+	}
 
 	if (fd >= 0) {
 		unsigned char sha1[20];