@@ -71,6 +71,9 @@ struct psr_ctx {
7171 struct psr_error psr_error ;
7272 size_t psr_datalen ;
7373 void * psr_data ;
74+ size_t psr_mdatalen ;
75+ void * psr_mdata ;
76+ bool psr_usemdata ;
7477};
7578
7679static void
@@ -81,14 +84,15 @@ ps_root_readerrorcb(void *arg, unsigned short events)
8184 struct psr_error * psr_error = & psr_ctx -> psr_error ;
8285 struct iovec iov [] = {
8386 { .iov_base = psr_error , .iov_len = sizeof (* psr_error ) },
84- { .iov_base = psr_ctx -> psr_data ,
85- .iov_len = psr_ctx -> psr_datalen },
87+ { .iov_base = NULL , .iov_len = 0 },
8688 };
8789 ssize_t len ;
8890 int exit_code = EXIT_FAILURE ;
8991
90- if (events & ELE_HANGUP )
92+ if (events & ELE_HANGUP ) {
93+ logerrx ("%s: hangup" , __func__ );
9194 goto out ;
95+ }
9296
9397 if (events != ELE_READ )
9498 logerrx ("%s: unexpected event 0x%04x" , __func__ , events );
@@ -100,11 +104,39 @@ ps_root_readerrorcb(void *arg, unsigned short events)
100104 goto out; \
101105 } while (0 /* CONSTCOND */ )
102106
103- len = readv (PS_ROOT_FD(ctx), iov, __arraycount(iov) );
107+ len = recv (PS_ROOT_FD(ctx), psr_error, sizeof(*psr_error), MSG_PEEK );
104108 if (len == -1 )
105109 PSR_ERROR (errno );
106110 else if ((size_t )len < sizeof (* psr_error ))
107111 PSR_ERROR (EINVAL );
112+
113+ if (psr_error -> psr_datalen > SSIZE_MAX )
114+ PSR_ERROR (ENOBUFS );
115+ if (psr_ctx -> psr_usemdata &&
116+ psr_error -> psr_datalen > psr_ctx -> psr_mdatalen )
117+ {
118+ void * d = realloc (psr_ctx -> psr_mdata , psr_error -> psr_datalen );
119+ if (d == NULL )
120+ PSR_ERROR (errno );
121+ psr_ctx -> psr_mdata = d ;
122+ psr_ctx -> psr_mdatalen = psr_error -> psr_datalen ;
123+ }
124+ if (psr_error -> psr_datalen != 0 ) {
125+ if (psr_ctx -> psr_usemdata )
126+ iov [1 ].iov_base = psr_ctx -> psr_mdata ;
127+ else {
128+ if (psr_error -> psr_datalen > psr_ctx -> psr_datalen )
129+ PSR_ERROR (ENOBUFS );
130+ iov [1 ].iov_base = psr_ctx -> psr_data ;
131+ }
132+ iov [1 ].iov_len = psr_error -> psr_datalen ;
133+ }
134+
135+ len = readv (PS_ROOT_FD (ctx ), iov , __arraycount (iov ));
136+ if (len == -1 )
137+ PSR_ERROR (errno );
138+ else if ((size_t )len != sizeof (* psr_error ) + psr_error -> psr_datalen )
139+ PSR_ERROR (EINVAL );
108140 exit_code = EXIT_SUCCESS ;
109141
110142out :
@@ -119,6 +151,7 @@ ps_root_readerror(struct dhcpcd_ctx *ctx, void *data, size_t len)
119151
120152 pc -> psr_data = data ;
121153 pc -> psr_datalen = len ;
154+ pc -> psr_usemdata = false;
122155 err = eloop_start (ctx -> ps_eloop );
123156 if (err < 0 )
124157 return err ;
@@ -127,73 +160,35 @@ ps_root_readerror(struct dhcpcd_ctx *ctx, void *data, size_t len)
127160 return pc -> psr_error .psr_result ;
128161}
129162
130- #ifdef PRIVSEP_GETIFADDRS
131- static void
132- ps_root_mreaderrorcb (void * arg , unsigned short events )
133- {
134- struct psr_ctx * psr_ctx = arg ;
135- struct dhcpcd_ctx * ctx = psr_ctx -> psr_ctx ;
136- struct psr_error * psr_error = & psr_ctx -> psr_error ;
137- struct iovec iov [] = {
138- { .iov_base = psr_error , .iov_len = sizeof (* psr_error ) },
139- { .iov_base = NULL , .iov_len = 0 },
140- };
141- ssize_t len ;
142- int exit_code = EXIT_FAILURE ;
143-
144- if (events != ELE_READ )
145- logerrx ("%s: unexpected event 0x%04x" , __func__ , events );
146-
147- len = recv (PS_ROOT_FD (ctx ), psr_error , sizeof (* psr_error ), MSG_PEEK );
148- if (len == -1 )
149- PSR_ERROR (errno );
150- else if ((size_t )len < sizeof (* psr_error ))
151- PSR_ERROR (EINVAL );
152-
153- if (psr_error -> psr_datalen > SSIZE_MAX )
154- PSR_ERROR (ENOBUFS );
155- else if (psr_error -> psr_datalen != 0 ) {
156- psr_ctx -> psr_data = malloc (psr_error -> psr_datalen );
157- if (psr_ctx -> psr_data == NULL )
158- PSR_ERROR (errno );
159- psr_ctx -> psr_datalen = psr_error -> psr_datalen ;
160- iov [1 ].iov_base = psr_ctx -> psr_data ;
161- iov [1 ].iov_len = psr_ctx -> psr_datalen ;
162- }
163-
164- len = readv (PS_ROOT_FD (ctx ), iov , __arraycount (iov ));
165- if (len == -1 )
166- PSR_ERROR (errno );
167- else if ((size_t )len != sizeof (* psr_error ) + psr_ctx -> psr_datalen )
168- PSR_ERROR (EINVAL );
169- exit_code = EXIT_SUCCESS ;
170-
171- out :
172- eloop_exit (ctx -> ps_eloop , exit_code );
173- }
174-
175163ssize_t
176164ps_root_mreaderror (struct dhcpcd_ctx * ctx , void * * data , size_t * len )
177165{
178- struct psr_ctx psr_ctx = {
179- .psr_ctx = ctx ,
180- };
181- int fd = PS_ROOT_FD (ctx ), err ;
182-
183- if (eloop_event_add (ctx -> ps_eloop , fd , ELE_READ ,
184- ps_root_mreaderrorcb , & psr_ctx ) == -1 )
185- return -1 ;
166+ struct psr_ctx * pc = ctx -> ps_root -> psp_data ;
167+ int err ;
168+ void * d ;
186169
187- err = eloop_start (ctx -> ps_eloop , & ctx -> sigset );
170+ pc -> psr_usemdata = true;
171+ err = eloop_start (ctx -> ps_eloop );
188172 if (err < 0 )
189173 return err ;
190174
191- errno = psr_ctx .psr_error .psr_errno ;
192- * data = psr_ctx .psr_data ;
193- * len = psr_ctx .psr_datalen ;
194- return psr_ctx .psr_error .psr_result ;
175+ if (pc -> psr_error .psr_datalen != 0 ) {
176+ if (pc -> psr_error .psr_datalen > pc -> psr_mdatalen ) {
177+ errno = EINVAL ;
178+ return -1 ;
179+ }
180+ d = malloc (pc -> psr_error .psr_datalen );
181+ if (d == NULL )
182+ return -1 ;
183+ memcpy (d , pc -> psr_mdata , pc -> psr_error .psr_datalen );
184+ } else
185+ d = NULL ;
186+
187+ errno = pc -> psr_error .psr_errno ;
188+ * data = d ;
189+ * len = pc -> psr_error .psr_datalen ;
190+ return pc -> psr_error .psr_result ;
195191}
196- #endif
197192
198193static ssize_t
199194ps_root_writeerror (struct dhcpcd_ctx * ctx , ssize_t result ,
@@ -863,6 +858,17 @@ ps_root_log(void *arg, unsigned short events)
863858 logerr (__func__ );
864859}
865860
861+ static void
862+ ps_root_freepsdata (void * arg )
863+ {
864+ struct psr_ctx * pc = arg ;
865+
866+ if (pc == NULL )
867+ return ;
868+ free (pc -> psr_mdata );
869+ free (pc );
870+ }
871+
866872pid_t
867873ps_root_start (struct dhcpcd_ctx * ctx )
868874{
@@ -891,8 +897,7 @@ ps_root_start(struct dhcpcd_ctx *ctx)
891897 return -1 ;
892898#endif
893899
894-
895- pc = malloc (sizeof (* pc ));
900+ pc = calloc (1 , sizeof (* pc ));
896901 if (pc == NULL )
897902 return -1 ;
898903 pc -> psr_ctx = ctx ;
@@ -903,6 +908,7 @@ ps_root_start(struct dhcpcd_ctx *ctx)
903908 free (pc );
904909 return -1 ;
905910 }
911+ psp -> psp_freedata = ps_root_freepsdata ;
906912 strlcpy (psp -> psp_name , "privileged proxy" , sizeof (psp -> psp_name ));
907913 pid = ps_startprocess (psp , ps_root_recvmsg , NULL ,
908914 ps_root_startcb , PSF_ELOOP );
970976ps_root_stop (struct dhcpcd_ctx * ctx )
971977{
972978 struct ps_process * psp = ctx -> ps_root ;
979+ int err ;
973980
974981 if (!(ctx -> options & DHCPCD_PRIVSEP ) ||
975982 ctx -> eloop == NULL )
@@ -1001,7 +1008,9 @@ ps_root_stop(struct dhcpcd_ctx *ctx)
10011008 return -1 ;
10021009 } /* else the root process has already exited :( */
10031010
1004- return ps_stopwait (ctx );
1011+ err = ps_stopwait (ctx );
1012+ ps_freeprocess (ctx -> ps_root );
1013+ return err ;
10051014}
10061015
10071016ssize_t
0 commit comments