@@ -71,20 +71,18 @@ 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 ;
74+ bool psr_mallocdata ;
7775};
7876
7977static ssize_t
80- ps_root_readerrorcb (struct psr_ctx * psr_ctx )
78+ ps_root_readerrorcb (struct psr_ctx * pc )
8179{
82- struct dhcpcd_ctx * ctx = psr_ctx -> psr_ctx ;
80+ struct dhcpcd_ctx * ctx = pc -> psr_ctx ;
8381 int fd = PS_ROOT_FD (ctx );
84- struct psr_error * psr_error = & psr_ctx -> psr_error ;
82+ struct psr_error * psr_error = & pc -> psr_error ;
8583 struct iovec iov [] = {
8684 { .iov_base = psr_error , .iov_len = sizeof (* psr_error ) },
87- { .iov_base = NULL , .iov_len = 0 },
85+ { .iov_base = pc -> psr_data , .iov_len = pc -> psr_datalen },
8886 };
8987 struct msghdr msg = { .msg_iov = iov , .msg_iovlen = __arraycount (iov ) };
9088 ssize_t len ;
@@ -99,8 +97,12 @@ ps_root_readerrorcb(struct psr_ctx *psr_ctx)
9997 if (eloop_waitfd (fd ) == -1 )
10098 PSR_ERROR (errno );
10199
100+ if (!pc -> psr_mallocdata )
101+ goto recv ;
102+
102103 /* We peek at the psr_error structure to tell us how much of a buffer
103104 * we need to read the whole packet. */
105+ msg .msg_iovlen -- ;
104106 len = recvmsg (fd , & msg , MSG_PEEK | MSG_WAITALL );
105107 if (len == -1 )
106108 PSR_ERROR (errno );
@@ -114,35 +116,18 @@ ps_root_readerrorcb(struct psr_ctx *psr_ctx)
114116 PSR_ERROR (EINVAL );
115117 }
116118
117- if (psr_ctx -> psr_usemdata &&
118- psr_error -> psr_datalen > psr_ctx -> psr_mdatalen )
119- {
120- void * d = realloc (psr_ctx -> psr_mdata , psr_error -> psr_datalen );
121-
122- /* If we failed to realloc then psr_mdatalen will be smaller
123- * than psr_datalen.
124- * The following recvmsg will get MSG_TRUNC so the malloc error
125- * will be reported there but more importantly the
126- * message will be correctly discarded from the queue. */
127- if (d != NULL ) {
128- psr_ctx -> psr_mdata = d ;
129- psr_ctx -> psr_mdatalen = psr_error -> psr_datalen ;
130- }
131- }
132- if (psr_error -> psr_datalen != 0 ) {
133- /* Set our buffers */
134- if (psr_ctx -> psr_usemdata ) {
135- iov [1 ].iov_base = psr_ctx -> psr_mdata ;
136- iov [1 ].iov_len = psr_ctx -> psr_mdatalen ;
137- } else {
138- iov [1 ].iov_base = psr_ctx -> psr_data ;
139- iov [1 ].iov_len = psr_ctx -> psr_datalen ;
140- }
141- /* We might require less than the buffer size */
142- if (iov [1 ].iov_len > psr_error -> psr_datalen )
143- iov [1 ].iov_len = psr_error -> psr_datalen ;
119+ /* No data to read? Unlikely but ... */
120+ if (psr_error -> psr_datalen == 0 )
121+ goto recv ;
122+
123+ pc -> psr_data = malloc (psr_error -> psr_datalen );
124+ if (pc -> psr_data != NULL ) {
125+ iov [1 ].iov_base = pc -> psr_data ;
126+ iov [1 ].iov_len = psr_error -> psr_datalen ;
127+ msg .msg_iovlen ++ ;
144128 }
145129
130+ recv :
146131 len = recvmsg (fd , & msg , MSG_WAITALL );
147132 if (len == -1 )
148133 PSR_ERROR (errno );
@@ -161,42 +146,35 @@ ps_root_readerrorcb(struct psr_ctx *psr_ctx)
161146ssize_t
162147ps_root_readerror (struct dhcpcd_ctx * ctx , void * data , size_t len )
163148{
164- struct psr_ctx * pc = ctx -> ps_root -> psp_data ;
149+ struct psr_ctx pc = {
150+ .psr_ctx = ctx ,
151+ .psr_data = data ,
152+ .psr_datalen = len ,
153+ .psr_mallocdata = false
154+ };
165155
166- pc -> psr_data = data ;
167- pc -> psr_datalen = len ;
168- pc -> psr_usemdata = false;
169- ps_root_readerrorcb (pc );
156+ ps_root_readerrorcb (& pc );
170157
171- errno = pc -> psr_error .psr_errno ;
172- return pc -> psr_error .psr_result ;
158+ errno = pc . psr_error .psr_errno ;
159+ return pc . psr_error .psr_result ;
173160}
174161
175162ssize_t
176163ps_root_mreaderror (struct dhcpcd_ctx * ctx , void * * data , size_t * len )
177164{
178- struct psr_ctx * pc = ctx -> ps_root -> psp_data ;
179- void * d ;
165+ struct psr_ctx pc = {
166+ .psr_ctx = ctx ,
167+ .psr_data = NULL ,
168+ .psr_datalen = 0 ,
169+ .psr_mallocdata = true
170+ };
180171
181- pc -> psr_usemdata = true;
182- ps_root_readerrorcb (pc );
172+ ps_root_readerrorcb (& pc );
183173
184- if (pc -> psr_error .psr_datalen != 0 ) {
185- if (pc -> psr_error .psr_datalen > pc -> psr_mdatalen ) {
186- errno = EINVAL ;
187- return -1 ;
188- }
189- d = malloc (pc -> psr_error .psr_datalen );
190- if (d == NULL )
191- return -1 ;
192- memcpy (d , pc -> psr_mdata , pc -> psr_error .psr_datalen );
193- } else
194- d = NULL ;
195-
196- errno = pc -> psr_error .psr_errno ;
197- * data = d ;
198- * len = pc -> psr_error .psr_datalen ;
199- return pc -> psr_error .psr_result ;
174+ errno = pc .psr_error .psr_errno ;
175+ * data = pc .psr_data ;
176+ * len = pc .psr_error .psr_datalen ;
177+ return pc .psr_error .psr_result ;
200178}
201179
202180static ssize_t
@@ -220,6 +198,8 @@ ps_root_writeerror(struct dhcpcd_ctx *ctx, ssize_t result,
220198 logdebugx ("%s: result %zd errno %d" , __func__ , result , errno );
221199#endif
222200
201+ if (len == 0 )
202+ msg .msg_iovlen = 1 ;
223203 err = sendmsg (fd , & msg , MSG_EOR );
224204
225205 /* Error sending the message? Try sending the error of sending. */
@@ -228,8 +208,8 @@ ps_root_writeerror(struct dhcpcd_ctx *ctx, ssize_t result,
228208 __func__ , result , data , len );
229209 psr .psr_result = err ;
230210 psr .psr_errno = errno ;
231- iov [ 1 ]. iov_base = NULL ;
232- iov [ 1 ]. iov_len = 0 ;
211+ psr . psr_datalen = 0 ;
212+ msg . msg_iovlen = 1 ;
233213 err = sendmsg (fd , & msg , MSG_EOR );
234214 }
235215
@@ -626,7 +606,7 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg)
626606 break ;
627607 }
628608
629- err = ps_root_writeerror (ctx , err , rlen != 0 ? rdata : 0 , rlen );
609+ err = ps_root_writeerror (ctx , err , rdata , rlen );
630610 if (free_rdata )
631611 free (rdata );
632612 return err ;
@@ -867,17 +847,6 @@ ps_root_log(void *arg, unsigned short events)
867847 logerr (__func__ );
868848}
869849
870- static void
871- ps_root_freepsdata (void * arg )
872- {
873- struct psr_ctx * pc = arg ;
874-
875- if (pc == NULL )
876- return ;
877- free (pc -> psr_mdata );
878- free (pc );
879- }
880-
881850pid_t
882851ps_root_start (struct dhcpcd_ctx * ctx )
883852{
@@ -888,7 +857,6 @@ ps_root_start(struct dhcpcd_ctx *ctx)
888857 struct ps_process * psp ;
889858 int logfd [2 ] = { -1 , -1 }, datafd [2 ] = { -1 , -1 };
890859 pid_t pid ;
891- struct psr_ctx * pc ;
892860
893861 if (xsocketpair (AF_UNIX , SOCK_SEQPACKET | SOCK_CXNB , 0 , logfd ) == -1 )
894862 return -1 ;
@@ -907,27 +875,15 @@ ps_root_start(struct dhcpcd_ctx *ctx)
907875 return -1 ;
908876#endif
909877
910- pc = calloc (1 , sizeof (* pc ));
911- if (pc == NULL )
912- return -1 ;
913- pc -> psr_ctx = ctx ;
914-
915878 psp = ctx -> ps_root = ps_newprocess (ctx , & id );
916879 if (psp == NULL )
917- {
918- free (pc );
919880 return -1 ;
920- }
921- psp -> psp_freedata = ps_root_freepsdata ;
881+
922882 strlcpy (psp -> psp_name , "privileged proxy" , sizeof (psp -> psp_name ));
923883 pid = ps_startprocess (psp , ps_root_recvmsg , NULL ,
924884 ps_root_startcb , PSF_ELOOP );
925- if (pid == -1 ) {
926- free (pc );
885+ if (pid == -1 )
927886 return -1 ;
928- }
929-
930- psp -> psp_data = pc ;
931887
932888 if (pid == 0 ) {
933889 ctx -> ps_log_fd = logfd [0 ]; /* Keep open to pass to processes */
0 commit comments