Commit 89db242a authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

media: cec: support CEC_MSG_FL_RAW

If this flag is set, then check for root permissions and skip
all message checks expect for the core checks (i.e. validate the
length etc.).
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent eabe3bc2
...@@ -720,6 +720,7 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, ...@@ -720,6 +720,7 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
struct cec_fh *fh, bool block) struct cec_fh *fh, bool block)
{ {
struct cec_data *data; struct cec_data *data;
bool is_raw = msg_is_raw(msg);
msg->rx_ts = 0; msg->rx_ts = 0;
msg->tx_ts = 0; msg->tx_ts = 0;
...@@ -735,10 +736,10 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, ...@@ -735,10 +736,10 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
/* Make sure the timeout isn't 0. */ /* Make sure the timeout isn't 0. */
msg->timeout = 1000; msg->timeout = 1000;
} }
if (msg->timeout) msg->flags &= CEC_MSG_FL_REPLY_TO_FOLLOWERS | CEC_MSG_FL_RAW;
msg->flags &= CEC_MSG_FL_REPLY_TO_FOLLOWERS;
else if (!msg->timeout)
msg->flags = 0; msg->flags &= ~CEC_MSG_FL_REPLY_TO_FOLLOWERS;
/* Sanity checks */ /* Sanity checks */
if (msg->len == 0 || msg->len > CEC_MAX_MSG_SIZE) { if (msg->len == 0 || msg->len > CEC_MAX_MSG_SIZE) {
...@@ -761,10 +762,16 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, ...@@ -761,10 +762,16 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
return -EINVAL; return -EINVAL;
} }
if (is_raw) {
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
} else {
/* A CDC-Only device can only send CDC messages */ /* A CDC-Only device can only send CDC messages */
if ((adap->log_addrs.flags & CEC_LOG_ADDRS_FL_CDC_ONLY) && if ((adap->log_addrs.flags & CEC_LOG_ADDRS_FL_CDC_ONLY) &&
(msg->len == 1 || msg->msg[1] != CEC_MSG_CDC_MESSAGE)) (msg->len == 1 || msg->msg[1] != CEC_MSG_CDC_MESSAGE)) {
dprintk(1, "%s: not a CDC message\n", __func__);
return -EINVAL; return -EINVAL;
}
if (msg->len >= 4 && msg->msg[1] == CEC_MSG_CDC_MESSAGE) { if (msg->len >= 4 && msg->msg[1] == CEC_MSG_CDC_MESSAGE) {
msg->msg[2] = adap->phys_addr >> 8; msg->msg[2] = adap->phys_addr >> 8;
...@@ -773,17 +780,18 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, ...@@ -773,17 +780,18 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
if (msg->len == 1) { if (msg->len == 1) {
if (cec_msg_destination(msg) == 0xf) { if (cec_msg_destination(msg) == 0xf) {
dprintk(1, "%s: invalid poll message\n", __func__); dprintk(1, "%s: invalid poll message\n",
__func__);
return -EINVAL; return -EINVAL;
} }
if (cec_has_log_addr(adap, cec_msg_destination(msg))) { if (cec_has_log_addr(adap, cec_msg_destination(msg))) {
/* /*
* If the destination is a logical address our adapter * If the destination is a logical address our
* has already claimed, then just NACK this. * adapter has already claimed, then just NACK
* It depends on the hardware what it will do with a * this. It depends on the hardware what it will
* POLL to itself (some OK this), so it is just as * do with a POLL to itself (some OK this), so
* easy to handle it here so the behavior will be * it is just as easy to handle it here so the
* consistent. * behavior will be consistent.
*/ */
msg->tx_ts = ktime_get_ns(); msg->tx_ts = ktime_get_ns();
msg->tx_status = CEC_TX_STATUS_NACK | msg->tx_status = CEC_TX_STATUS_NACK |
...@@ -797,7 +805,8 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, ...@@ -797,7 +805,8 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
} }
if (msg->len > 1 && !cec_msg_is_broadcast(msg) && if (msg->len > 1 && !cec_msg_is_broadcast(msg) &&
cec_has_log_addr(adap, cec_msg_destination(msg))) { cec_has_log_addr(adap, cec_msg_destination(msg))) {
dprintk(1, "%s: destination is the adapter itself\n", __func__); dprintk(1, "%s: destination is the adapter itself\n",
__func__);
return -EINVAL; return -EINVAL;
} }
if (msg->len > 1 && adap->is_configured && if (msg->len > 1 && adap->is_configured &&
...@@ -806,11 +815,19 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg, ...@@ -806,11 +815,19 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
__func__, cec_msg_initiator(msg)); __func__, cec_msg_initiator(msg));
return -EINVAL; return -EINVAL;
} }
if (!adap->is_configured && !adap->is_configuring) { if (!adap->is_configured && !adap->is_configuring &&
if (adap->needs_hpd || msg->msg[0] != 0xf0) { msg->msg[0] != 0xf0) {
dprintk(1, "%s: adapter is unconfigured\n", __func__); dprintk(1, "%s: adapter is unconfigured\n", __func__);
return -ENONET; return -ENONET;
} }
}
if (!adap->is_configured && !adap->is_configuring) {
if (adap->needs_hpd) {
dprintk(1, "%s: adapter is unconfigured and needs HPD\n",
__func__);
return -ENONET;
}
if (msg->reply) { if (msg->reply) {
dprintk(1, "%s: invalid msg->reply\n", __func__); dprintk(1, "%s: invalid msg->reply\n", __func__);
return -EINVAL; return -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment