summaryrefslogtreecommitdiff
path: root/debian/patches/exec_filename0004-This-patch-is-an-amendment-of-exec_filename_exec.pat.patch
blob: 290aac47f65fb9c477ca8fdc0398b38533ea6031 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
From f011579ac300620fe6e513c92080cf5e576d5e87 Mon Sep 17 00:00:00 2001
From: Justus Winter <4winter@informatik.uni-hamburg.de>
Date: Sun, 13 Sep 2015 14:06:59 +0200
Subject: [PATCH hurd 4/4] This patch is an amendment of
 exec_filename_exec.patch.

If file_name_exec is not given, check_hashbang will try to locate the
file. If argv[0] contains a '/', the file path is assumed to be
absolute and it will try to open the file. Otherwise, the file is
searched in the PATH. In either case, the resulting file identity port
is compared to the identity port of the original file handle passed to
check_hashbang.

exec_filename_exec.patch explicitly provides the script files path in
file_name_exec. According to the comment, if this path is provided, it
is assumed to be the path to the script file and no attempt at
locating the script file is done. However, the identity ports are
still compared. This cannot succeed if fakeroot or chroot is used,
because the process doing the exec and thus the initial file lookup is
running in the chrooted environment, while the exec server is not.

Fix this by skipping the identity test if file_name_exec is provided.

* exec/hashexec.c (check_hashbang): Skip the file identity test if the
  file_name_exec is provided.
---
 exec/hashexec.c | 93 +++++++++++++++++++++++++++++++--------------------------
 1 file changed, 51 insertions(+), 42 deletions(-)

diff --git a/exec/hashexec.c b/exec/hashexec.c
index c971279..c2eda5b 100644
--- a/exec/hashexec.c
+++ b/exec/hashexec.c
@@ -231,11 +231,12 @@ check_hashbang (struct execdata *e,
 	  else if (! (flags & EXEC_SECURE))
 	    {
 	      /* Try to figure out the file's name.  If FILE_NAME_EXEC
-		 is not NULL, then it's the file's name.  Otherwise we
-		 guess that if ARGV[0] contains a slash, it might be
-		 the name of the file; and that if it contains no slash,
-		 looking for files named by ARGV[0] in the `PATH'
-		 environment variable might find it.  */
+		 is not NULL and not the empty string, then it's the
+		 file's name.  Otherwise we guess that if ARGV[0]
+		 contains a slash, it might be the name of the file;
+		 and that if it contains no slash, looking for files
+		 named by ARGV[0] in the `PATH' environment variable
+		 might find it.  */
 
 	      error_t error;
 	      char *name;
@@ -271,51 +272,59 @@ check_hashbang (struct execdata *e,
 		  return err;
 		}
 
-	      error = io_identity (file, &fileid, &filefsid, &fileno);
-	      if (error)
-		goto out;
-	      mach_port_deallocate (mach_task_self (), filefsid);
-
-	      if (memchr (argv, '\0', argvlen) == NULL)
-		{
-		  name = alloca (argvlen + 1);
-		  bcopy (argv, name, argvlen);
-		  name[argvlen] = '\0';
-		}
-	      else
-		name = argv;
-
 	      if (file_name_exec && file_name_exec[0] != '\0')
-		error = lookup (name = file_name_exec, 0, &name_file);
-	      else if (strchr (name, '/') != NULL)
-		error = lookup (name, 0, &name_file);
-	      else if ((error = hurd_catch_signal
-			(sigmask (SIGBUS) | sigmask (SIGSEGV),
-			 (vm_address_t) envp, (vm_address_t) envp + envplen,
-			 &search_path, SIG_ERR)))
-		name_file = MACH_PORT_NULL;
-
-	      if (!error && name_file != MACH_PORT_NULL)
+		name = file_name_exec;
+	      else
 		{
-		  mach_port_t id, fsid;
-		  ino_t ino;
-		  error = io_identity (name_file, &id, &fsid, &ino);
-		  mach_port_deallocate (mach_task_self (), name_file);
-		  if (!error)
+		  /* Try to locate the file.  */
+		  error = io_identity (file, &fileid, &filefsid, &fileno);
+		  if (error)
+		    goto out;
+		  mach_port_deallocate (mach_task_self (), filefsid);
+
+		  if (memchr (argv, '\0', argvlen) == NULL)
 		    {
-		      mach_port_deallocate (mach_task_self (), fsid);
-		      mach_port_deallocate (mach_task_self (), id);
+		      name = alloca (argvlen + 1);
+		      bcopy (argv, name, argvlen);
+		      name[argvlen] = '\0';
 		    }
-		  if (!error && id == fileid)
+		  else
+		    name = argv;
+
+		  if (strchr (name, '/') != NULL)
+		    error = lookup (name, 0, &name_file);
+		  else if ((error = hurd_catch_signal
+			    (sigmask (SIGBUS) | sigmask (SIGSEGV),
+			     (vm_address_t) envp, (vm_address_t) envp + envplen,
+			     &search_path, SIG_ERR)))
+		    name_file = MACH_PORT_NULL;
+
+		  /* See whether we found the right file.  */
+		  if (!error && name_file != MACH_PORT_NULL)
 		    {
-		      file_name = name;
-		      free_file_name = free_name;
+		      mach_port_t id, fsid;
+		      ino_t ino;
+		      error = io_identity (name_file, &id, &fsid, &ino);
+		      mach_port_deallocate (mach_task_self (), name_file);
+		      if (!error)
+			{
+			  mach_port_deallocate (mach_task_self (), fsid);
+			  mach_port_deallocate (mach_task_self (), id);
+			  if (id != fileid)
+			    error = 1;
+			}
 		    }
-		  else if (free_name)
-		    free (name);
+
+		  mach_port_deallocate (mach_task_self (), fileid);
 		}
 
-	      mach_port_deallocate (mach_task_self (), fileid);
+	      if (!error)
+		{
+		  file_name = name;
+		  free_file_name = free_name;
+		}
+	      else if (free_name)
+		free (name);
 	    }
 
 	  if (file_name == NULL)
-- 
2.1.4