From 4af24949b94eda84b4b74d77b9164cf3fe0eccf9 Mon Sep 17 00:00:00 2001 From: Andre Mauricio Zelak Date: Mon, 12 Jun 2023 18:18:29 -0300 Subject: [PATCH 35/54] clock: Add read-only UDS port for monitoring. Add a second UDS port to allow untrusted applications to monitor ptp4l. On this "read-only" UDS port disable non-GET actions and forwarding. The path can be configured with the uds_ro_address option (default is /var/run/ptp4lro). Forwarding is disabled to limit the access to the local ptp4l instance. Subscriptions are not enabled to prevent the applications from making a large number of subscriptions or interfere with applications that have access to the read-write UDS port. Signed-off-by: Miroslav Lichvar [commit 6823e077b2466dcc3c7cbce8ab384b0ef9a62811 upstream] Signed-off-by: Andre Mauricio Zelak --- clock.c | 72 +++++++++++++++++++++++++++++++++++++-------- config.c | 1 + configs/default.cfg | 1 + ptp4l.8 | 6 ++++ 4 files changed, 67 insertions(+), 13 deletions(-) diff --git a/clock.c b/clock.c index d653c33..869e35d 100644 --- a/clock.c +++ b/clock.c @@ -96,9 +96,10 @@ struct clock { struct ClockIdentity best_id; LIST_HEAD(ports_head, port) ports; struct port *uds_rw_port; + struct port *uds_ro_port; struct pollfd *pollfd; int pollfd_valid; - int nports; /* does not include the UDS port */ + int nports; /* does not include the two UDS ports */ int last_port_number; int sde; int free_running; @@ -130,6 +131,7 @@ struct clock { int stats_interval; struct clockcheck *sanity_check; struct interface *uds_rw_if; + struct interface *uds_ro_if; LIST_HEAD(clock_subscribers_head, clock_subscriber) subscribers; struct monitor *slave_event_monitor; }; @@ -266,12 +268,14 @@ void clock_destroy(struct clock *c) struct port *p, *tmp; interface_destroy(c->uds_rw_if); + interface_destroy(c->uds_ro_if); clock_flush_subscriptions(c); LIST_FOREACH_SAFE(p, &c->ports, list, tmp) { clock_remove_port(c, p); } monitor_destroy(c->slave_event_monitor); port_close(c->uds_rw_port); + port_close(c->uds_ro_port); free(c->pollfd); if (c->clkid != CLOCK_REALTIME) { phc_close(c->clkid); @@ -441,7 +445,7 @@ static int clock_management_fill_response(struct clock *c, struct port *p, break; case TLV_SUBSCRIBE_EVENTS_NP: if (p != c->uds_rw_port) { - /* Only the UDS port allowed. */ + /* Only the UDS-RW port allowed. */ break; } sen = (struct subscribe_events_np *)tlv->data; @@ -772,6 +776,10 @@ static int clock_utc_correct(struct clock *c, tmv_t ingress) static int forwarding(struct clock *c, struct port *p) { enum port_state ps = port_state(p); + + if (p == c->uds_ro_port) + return 0; + switch (ps) { case PS_MASTER: case PS_GRAND_MASTER: @@ -816,7 +824,7 @@ static int clock_add_port(struct clock *c, const char *phc_device, { struct port *p, *piter, *lastp = NULL; - if (clock_resize_pollfd(c, c->nports + 1)) { + if (clock_resize_pollfd(c, c->nports + 2)) { return -1; } p = port_open(phc_device, phc_index, timestamping, @@ -1041,6 +1049,7 @@ struct clock *clock_create(enum clock_type type, struct config *config, } /* Configure the UDS. */ + uds_ifname = config_get_string(config, NULL, "uds_address"); c->uds_rw_if = interface_create(uds_ifname); if (config_set_section_int(config, interface_name(c->uds_rw_if), @@ -1060,6 +1069,25 @@ struct clock *clock_create(enum clock_type type, struct config *config, return NULL; } + uds_ifname = config_get_string(config, NULL, "uds_ro_address"); + c->uds_ro_if = interface_create(uds_ifname); + if (config_set_section_int(config, interface_name(c->uds_ro_if), + "announceReceiptTimeout", 0)) { + return NULL; + } + if (config_set_section_int(config, interface_name(c->uds_ro_if), + "delay_mechanism", DM_AUTO)) { + return NULL; + } + if (config_set_section_int(config, interface_name(c->uds_ro_if), + "network_transport", TRANS_UDS)) { + return NULL; + } + if (config_set_section_int(config, interface_name(c->uds_ro_if), + "delay_filter_length", 1)) { + return NULL; + } + c->config = config; c->free_running = config_get_int(config, NULL, "free_running"); c->freq_est_interval = config_get_int(config, NULL, "freq_est_interval"); @@ -1177,11 +1205,18 @@ struct clock *clock_create(enum clock_type type, struct config *config, return NULL; } - /* Create the UDS interface. */ + /* Create the UDS interfaces. */ + c->uds_rw_port = port_open(phc_device, phc_index, timestamping, 0, c->uds_rw_if, c); if (!c->uds_rw_port) { - pr_err("failed to open the UDS port"); + pr_err("failed to open the UDS-RW port"); + return NULL; + } + c->uds_ro_port = port_open(phc_device, phc_index, timestamping, 0, + c->uds_ro_if, c); + if (!c->uds_ro_port) { + pr_err("failed to open the UDS-RO port"); return NULL; } clock_fda_changed(c); @@ -1206,6 +1241,7 @@ struct clock *clock_create(enum clock_type type, struct config *config, port_dispatch(p, EV_INITIALIZE, 0); } port_dispatch(c->uds_rw_port, EV_INITIALIZE, 0); + port_dispatch(c->uds_ro_port, EV_INITIALIZE, 0); return c; } @@ -1276,9 +1312,9 @@ static int clock_resize_pollfd(struct clock *c, int new_nports) { struct pollfd *new_pollfd; - /* Need to allocate one whole extra block of fds for UDS. */ + /* Need to allocate two whole extra blocks of fds for UDS ports. */ new_pollfd = realloc(c->pollfd, - (new_nports + 1) * N_CLOCK_PFD * + (new_nports + 2) * N_CLOCK_PFD * sizeof(struct pollfd)); if (!new_pollfd) { return -1; @@ -1314,6 +1350,8 @@ static void clock_check_pollfd(struct clock *c) dest += N_CLOCK_PFD; } clock_fill_pollfd(dest, c->uds_rw_port); + dest += N_CLOCK_PFD; + clock_fill_pollfd(dest, c->uds_ro_port); c->pollfd_valid = 1; } @@ -1329,7 +1367,8 @@ static int clock_do_forward_mgmt(struct clock *c, if (in == out || !forwarding(c, out)) return 0; - /* Don't forward any requests to the UDS port. */ + /* Don't forward any requests to the UDS-RW port + (the UDS-RO port doesn't allow any forwarding). */ if (out == c->uds_rw_port) { switch (management_action(msg)) { case GET: @@ -1414,7 +1453,7 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg) return changed; } if (p != c->uds_rw_port) { - /* Sorry, only allowed on the UDS port. */ + /* Sorry, only allowed on the UDS-RW port. */ clock_management_send_error(p, msg, TLV_NOT_SUPPORTED); return changed; } @@ -1423,7 +1462,7 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg) break; case COMMAND: if (p != c->uds_rw_port) { - /* Sorry, only allowed on the UDS port. */ + /* Sorry, only allowed on the UDS-RW port. */ clock_management_send_error(p, msg, TLV_NOT_SUPPORTED); return changed; } @@ -1435,7 +1474,7 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg) switch (mgt->id) { case TLV_PORT_PROPERTIES_NP: if (p != c->uds_rw_port) { - /* Only the UDS port allowed. */ + /* Only the UDS-RW port allowed. */ clock_management_send_error(p, msg, TLV_NOT_SUPPORTED); return 0; } @@ -1548,7 +1587,7 @@ int clock_poll(struct clock *c) struct port *p; clock_check_pollfd(c); - cnt = poll(c->pollfd, (c->nports + 1) * N_CLOCK_PFD, -1); + cnt = poll(c->pollfd, (c->nports + 2) * N_CLOCK_PFD, -1); if (cnt < 0) { if (EINTR == errno) { return 0; @@ -1602,7 +1641,7 @@ int clock_poll(struct clock *c) cur += N_CLOCK_PFD; } - /* Check the UDS port. */ + /* Check the UDS ports. */ for (i = 0; i < N_POLLFD; i++) { if (cur[i].revents & (POLLIN|POLLPRI)) { event = port_event(c->uds_rw_port, i); @@ -1611,6 +1650,13 @@ int clock_poll(struct clock *c) } } } + cur += N_CLOCK_PFD; + for (i = 0; i < N_POLLFD; i++) { + if (cur[i].revents & (POLLIN|POLLPRI)) { + event = port_event(c->uds_ro_port, i); + /* sde is not expected on the UDS-RO port */ + } + } if (c->sde) { handle_state_decision_event(c); diff --git a/config.c b/config.c index fea7f67..d45e948 100644 --- a/config.c +++ b/config.c @@ -323,6 +323,7 @@ struct config_item config_tab[] = { PORT_ITEM_INT("udp_ttl", 1, 1, 255), PORT_ITEM_INT("udp6_scope", 0x0E, 0x00, 0x0F), GLOB_ITEM_STR("uds_address", "/var/run/ptp4l"), + GLOB_ITEM_STR("uds_ro_address", "/var/run/ptp4lro"), PORT_ITEM_INT("unicast_listen", 0, 0, 1), PORT_ITEM_INT("unicast_master_table", 0, 0, INT_MAX), PORT_ITEM_INT("unicast_req_duration", 3600, 10, INT_MAX), diff --git a/configs/default.cfg b/configs/default.cfg index 8c19129..d5bab7d 100644 --- a/configs/default.cfg +++ b/configs/default.cfg @@ -90,6 +90,7 @@ p2p_dst_mac 01:80:C2:00:00:0E udp_ttl 1 udp6_scope 0x0E uds_address /var/run/ptp4l +uds_ro_address /var/run/ptp4lro # # Default interface options # diff --git a/ptp4l.8 b/ptp4l.8 index b179b81..f9bd228 100644 --- a/ptp4l.8 +++ b/ptp4l.8 @@ -615,6 +615,12 @@ is only relevant with IPv6 transport. See RFC 4291. The default is Specifies the address of the UNIX domain socket for receiving local management messages. The default is /var/run/ptp4l. .TP +.B uds_ro_address +Specifies the address of the second UNIX domain socket for receiving local +management messages, which is restricted to GET actions and does not forward +messages to other ports. Access to this socket can be given to untrusted +applications for monitoring purposes. The default is /var/run/ptp4lro. +.TP .B dscp_event Defines the Differentiated Services Codepoint (DSCP) to be used for PTP event messages. Must be a value between 0 and 63. There are several media -- 2.25.1