mirror of
https://gitlab.freedesktop.org/libinput/libei.git
synced 2026-05-23 19:08:15 +02:00
util: Protect system calls against signals
Most system calls will fail if interrupted by a SIGALRM. Make sure we block SIGALRM prior to do the syscall, and restore the set of signals afterwards. Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
This commit is contained in:
parent
085f96c3bb
commit
0ac9b1b02d
2 changed files with 48 additions and 20 deletions
|
|
@ -47,7 +47,9 @@ xread_with_fds(int fd, void *buf, size_t count, int **fds)
|
|||
.msg_controllen = sizeof(control),
|
||||
};
|
||||
|
||||
sigset_t old_mask = signals_block();
|
||||
int received = xerrno(recvmsg(fd, &msg, 0));
|
||||
signals_release(old_mask);
|
||||
if (received > 0) {
|
||||
*fds = NULL;
|
||||
|
||||
|
|
@ -110,7 +112,11 @@ xsend_with_fd(int fd, const void *buf, size_t len, int *fds)
|
|||
header->cmsg_type = SCM_RIGHTS;
|
||||
memcpy(CMSG_DATA(CMSG_FIRSTHDR(&msg)), fds, nfds * sizeof(int));
|
||||
|
||||
return xerrno(sendmsg(fd, &msg, MSG_NOSIGNAL));
|
||||
sigset_t old_mask = signals_block();
|
||||
int sent = xerrno(sendmsg(fd, &msg, MSG_NOSIGNAL));
|
||||
signals_release(old_mask);
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
/* consider this struct opaque */
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
/**
|
||||
* Blocks the SIGALRM signal.
|
||||
*
|
||||
* @return the previous set of signals to pass to release_signals()
|
||||
* @return the previous set of signals to pass to signals_release()
|
||||
*/
|
||||
static inline sigset_t
|
||||
signals_block(void)
|
||||
|
|
@ -61,7 +61,7 @@ signals_block(void)
|
|||
/**
|
||||
* Release the SIGALRM signal.
|
||||
*
|
||||
* @param mask: The previous set of signals as returned by block_signals().
|
||||
* @param mask: The previous set of signals as returned by signals_block().
|
||||
*/
|
||||
static inline void
|
||||
signals_release(sigset_t mask)
|
||||
|
|
@ -81,12 +81,15 @@ xerrno(int value) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Wrapper around close(). It checks for fd != -1 to satisfy coverity and
|
||||
* friends and always returns -1.
|
||||
* Wrapper around close() that blocks the SIGALRM signal. It checks for
|
||||
* fd != -1 to satisfy coverity and friends and always returns -1.
|
||||
*/
|
||||
static inline int
|
||||
xclose(int fd) {
|
||||
sigset_t old_mask = signals_block();
|
||||
if (fd != -1) close(fd);
|
||||
signals_release(old_mask);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -97,42 +100,56 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(FILE *, fclose);
|
|||
#define _cleanup_fclose_ _cleanup_(fclosep)
|
||||
|
||||
/**
|
||||
* Wrapper around read(). Returns the number of bytes read or a negative
|
||||
* errno on failure.
|
||||
* Wrapper around read() that blocks the SIGALRM signal.
|
||||
* Returns the number of bytes read or a negative errno on failure.
|
||||
*/
|
||||
static inline int
|
||||
xread(int fd, void *buf, size_t count)
|
||||
{
|
||||
return xerrno(read(fd, buf, count));
|
||||
sigset_t old_mask = signals_block();
|
||||
int n = xerrno(read(fd, buf, count));
|
||||
signals_release(old_mask);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around read(). Returns the number of bytes read or a negative
|
||||
* errno on failure. Any fds passed along with the message
|
||||
* are stored in the -1-terminated allocated fds array, to be freed by the
|
||||
* caller. Where no fds were passed, the array is NULL.
|
||||
* Wrapper around read() that blocks the SIGALRM signal.
|
||||
* Returns the number of bytes read or a negative errno on failure.
|
||||
* Any fds passed along with the message are stored in the -1-terminated
|
||||
* allocated fds array, to be freed by the caller. Where no fds were
|
||||
* passed, the array is NULL.
|
||||
*/
|
||||
int
|
||||
xread_with_fds(int fd, void *buf, size_t count, int **fds);
|
||||
|
||||
/**
|
||||
* Wrapper around write(). Returns the number of bytes written or a negative
|
||||
* errno on failure.
|
||||
* Wrapper around write() that blocks the SIGALRM signal.
|
||||
* Returns the number of bytes written or a negative errno on failure.
|
||||
*/
|
||||
static inline int
|
||||
xwrite(int fd, const void *buf, size_t count)
|
||||
{
|
||||
return xerrno(write(fd, buf, count));
|
||||
sigset_t old_mask = signals_block();
|
||||
int n = xerrno(write(fd, buf, count));
|
||||
signals_release(old_mask);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around send() that always sets MSG_NOSIGNAL. Returns the number
|
||||
* of bytes written or a negative errno on failure.
|
||||
* Wrapper around send() that always sets MSG_NOSIGNAL and blocks the
|
||||
* SIGALRM signal.
|
||||
* Returns the number of bytes written or a negative errno on failure.
|
||||
*/
|
||||
static inline int
|
||||
xsend(int fd, const void *buf, size_t len)
|
||||
{
|
||||
return xerrno(send(fd, buf, len, MSG_NOSIGNAL));
|
||||
sigset_t old_mask = signals_block();
|
||||
int n = xerrno(send(fd, buf, len, MSG_NOSIGNAL));
|
||||
signals_release(old_mask);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -158,14 +175,19 @@ xconnect(const char *path)
|
|||
if (!xsnprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path))
|
||||
return -EINVAL;
|
||||
|
||||
sigset_t old_mask = signals_block();
|
||||
int sockfd = socket(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK, 0);
|
||||
if (sockfd == -1)
|
||||
return -errno;
|
||||
goto fail;
|
||||
|
||||
if (connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1)
|
||||
return -errno;
|
||||
goto fail;
|
||||
|
||||
signals_release(old_mask);
|
||||
return sockfd;
|
||||
fail:
|
||||
signals_release(old_mask);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue