This adds SMACK label configuration options to socket units. SMACK labels should be applied to most objects on disk well before execution time, but two items remain that are generated dynamically at run time that require SMACK labels to be set in order to enforce MAC on all objects. Files on disk can be labelled using package management. For device nodes, simple udev rules are sufficient to add SMACK labels at boot/insertion time. Sockets can be created at run time and systemd does just that for several services. In order to protect FIFO's and UNIX domain sockets, we must instruct systemd to apply SMACK labels at runtime. This patch adds the following options: Smack - applicable to FIFO's. SmackIpIn/SmackIpOut - applicable to sockets. No external dependencies are required to support SMACK, as setting the labels is done using fsetxattr(). The labels can be set on a kernel that does not have SMACK enabled either, so there is no need to #ifdef any of this code out. For more information about SMACK, please see Documentation/Smack.txt in the kernel source code. v3 of this patch changes the config options to be CamelCased.
176 lines
4.6 KiB
C
176 lines
4.6 KiB
C
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
|
|
|
#pragma once
|
|
|
|
/***
|
|
This file is part of systemd.
|
|
|
|
Copyright 2010 Lennart Poettering
|
|
|
|
systemd is free software; you can redistribute it and/or modify it
|
|
under the terms of the GNU Lesser General Public License as published by
|
|
the Free Software Foundation; either version 2.1 of the License, or
|
|
(at your option) any later version.
|
|
|
|
systemd is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
|
***/
|
|
|
|
typedef struct Socket Socket;
|
|
|
|
#include "manager.h"
|
|
#include "unit.h"
|
|
#include "socket-util.h"
|
|
#include "mount.h"
|
|
#include "service.h"
|
|
|
|
typedef enum SocketState {
|
|
SOCKET_DEAD,
|
|
SOCKET_START_PRE,
|
|
SOCKET_START_POST,
|
|
SOCKET_LISTENING,
|
|
SOCKET_RUNNING,
|
|
SOCKET_STOP_PRE,
|
|
SOCKET_STOP_PRE_SIGTERM,
|
|
SOCKET_STOP_PRE_SIGKILL,
|
|
SOCKET_STOP_POST,
|
|
SOCKET_FINAL_SIGTERM,
|
|
SOCKET_FINAL_SIGKILL,
|
|
SOCKET_FAILED,
|
|
_SOCKET_STATE_MAX,
|
|
_SOCKET_STATE_INVALID = -1
|
|
} SocketState;
|
|
|
|
typedef enum SocketExecCommand {
|
|
SOCKET_EXEC_START_PRE,
|
|
SOCKET_EXEC_START_POST,
|
|
SOCKET_EXEC_STOP_PRE,
|
|
SOCKET_EXEC_STOP_POST,
|
|
_SOCKET_EXEC_COMMAND_MAX,
|
|
_SOCKET_EXEC_COMMAND_INVALID = -1
|
|
} SocketExecCommand;
|
|
|
|
typedef enum SocketType {
|
|
SOCKET_SOCKET,
|
|
SOCKET_FIFO,
|
|
SOCKET_SPECIAL,
|
|
SOCKET_MQUEUE,
|
|
_SOCKET_FIFO_MAX,
|
|
_SOCKET_FIFO_INVALID = -1
|
|
} SocketType;
|
|
|
|
typedef enum SocketResult {
|
|
SOCKET_SUCCESS,
|
|
SOCKET_FAILURE_RESOURCES,
|
|
SOCKET_FAILURE_TIMEOUT,
|
|
SOCKET_FAILURE_EXIT_CODE,
|
|
SOCKET_FAILURE_SIGNAL,
|
|
SOCKET_FAILURE_CORE_DUMP,
|
|
SOCKET_FAILURE_SERVICE_FAILED_PERMANENT,
|
|
_SOCKET_RESULT_MAX,
|
|
_SOCKET_RESULT_INVALID = -1
|
|
} SocketResult;
|
|
|
|
typedef struct SocketPort {
|
|
SocketType type;
|
|
int fd;
|
|
|
|
SocketAddress address;
|
|
char *path;
|
|
Watch fd_watch;
|
|
|
|
LIST_FIELDS(struct SocketPort, port);
|
|
} SocketPort;
|
|
|
|
struct Socket {
|
|
Unit meta;
|
|
|
|
LIST_HEAD(SocketPort, ports);
|
|
|
|
unsigned n_accepted;
|
|
unsigned n_connections;
|
|
unsigned max_connections;
|
|
|
|
unsigned backlog;
|
|
usec_t timeout_usec;
|
|
|
|
ExecCommand* exec_command[_SOCKET_EXEC_COMMAND_MAX];
|
|
ExecContext exec_context;
|
|
KillContext kill_context;
|
|
|
|
/* For Accept=no sockets refers to the one service we'll
|
|
activate. For Accept=yes sockets is either NULL, or filled
|
|
when the next service we spawn. */
|
|
UnitRef service;
|
|
|
|
SocketState state, deserialized_state;
|
|
|
|
Watch timer_watch;
|
|
|
|
ExecCommand* control_command;
|
|
SocketExecCommand control_command_id;
|
|
pid_t control_pid;
|
|
|
|
mode_t directory_mode;
|
|
mode_t socket_mode;
|
|
|
|
SocketResult result;
|
|
|
|
bool accept;
|
|
|
|
/* Socket options */
|
|
bool keep_alive;
|
|
bool free_bind;
|
|
bool transparent;
|
|
bool broadcast;
|
|
bool pass_cred;
|
|
bool pass_sec;
|
|
int priority;
|
|
int mark;
|
|
size_t receive_buffer;
|
|
size_t send_buffer;
|
|
int ip_tos;
|
|
int ip_ttl;
|
|
size_t pipe_size;
|
|
char *bind_to_device;
|
|
char *tcp_congestion;
|
|
long mq_maxmsg;
|
|
long mq_msgsize;
|
|
|
|
/* Only for INET6 sockets: issue IPV6_V6ONLY sockopt */
|
|
SocketAddressBindIPv6Only bind_ipv6_only;
|
|
|
|
char *smack;
|
|
char *smack_ip_in;
|
|
char *smack_ip_out;
|
|
};
|
|
|
|
/* Called from the service code when collecting fds */
|
|
int socket_collect_fds(Socket *s, int **fds, unsigned *n_fds);
|
|
|
|
/* Called from the service when it shut down */
|
|
void socket_notify_service_dead(Socket *s, bool failed_permanent);
|
|
|
|
/* Called from the mount code figure out if a mount is a dependency of
|
|
* any of the sockets of this socket */
|
|
int socket_add_one_mount_link(Socket *s, Mount *m);
|
|
|
|
/* Called from the service code when a per-connection service ended */
|
|
void socket_connection_unref(Socket *s);
|
|
|
|
extern const UnitVTable socket_vtable;
|
|
|
|
const char* socket_state_to_string(SocketState i);
|
|
SocketState socket_state_from_string(const char *s);
|
|
|
|
const char* socket_exec_command_to_string(SocketExecCommand i);
|
|
SocketExecCommand socket_exec_command_from_string(const char *s);
|
|
|
|
const char* socket_result_to_string(SocketResult i);
|
|
SocketResult socket_result_from_string(const char *s);
|