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: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
This commit is contained in:
parent
eabe3bc268
commit
89db242aa3
@ -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,
|
|||||||
/* 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,54 +762,70 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A CDC-Only device can only send CDC messages */
|
if (is_raw) {
|
||||||
if ((adap->log_addrs.flags & CEC_LOG_ADDRS_FL_CDC_ONLY) &&
|
if (!capable(CAP_SYS_RAWIO))
|
||||||
(msg->len == 1 || msg->msg[1] != CEC_MSG_CDC_MESSAGE))
|
return -EPERM;
|
||||||
return -EINVAL;
|
} else {
|
||||||
|
/* A CDC-Only device can only send CDC messages */
|
||||||
if (msg->len >= 4 && msg->msg[1] == CEC_MSG_CDC_MESSAGE) {
|
if ((adap->log_addrs.flags & CEC_LOG_ADDRS_FL_CDC_ONLY) &&
|
||||||
msg->msg[2] = adap->phys_addr >> 8;
|
(msg->len == 1 || msg->msg[1] != CEC_MSG_CDC_MESSAGE)) {
|
||||||
msg->msg[3] = adap->phys_addr & 0xff;
|
dprintk(1, "%s: not a CDC message\n", __func__);
|
||||||
}
|
|
||||||
|
|
||||||
if (msg->len == 1) {
|
|
||||||
if (cec_msg_destination(msg) == 0xf) {
|
|
||||||
dprintk(1, "%s: invalid poll message\n", __func__);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (cec_has_log_addr(adap, cec_msg_destination(msg))) {
|
|
||||||
/*
|
if (msg->len >= 4 && msg->msg[1] == CEC_MSG_CDC_MESSAGE) {
|
||||||
* If the destination is a logical address our adapter
|
msg->msg[2] = adap->phys_addr >> 8;
|
||||||
* has already claimed, then just NACK this.
|
msg->msg[3] = adap->phys_addr & 0xff;
|
||||||
* It depends on the hardware what it will do with a
|
}
|
||||||
* POLL to itself (some OK this), so it is just as
|
|
||||||
* easy to handle it here so the behavior will be
|
if (msg->len == 1) {
|
||||||
* consistent.
|
if (cec_msg_destination(msg) == 0xf) {
|
||||||
*/
|
dprintk(1, "%s: invalid poll message\n",
|
||||||
msg->tx_ts = ktime_get_ns();
|
__func__);
|
||||||
msg->tx_status = CEC_TX_STATUS_NACK |
|
return -EINVAL;
|
||||||
CEC_TX_STATUS_MAX_RETRIES;
|
}
|
||||||
msg->tx_nack_cnt = 1;
|
if (cec_has_log_addr(adap, cec_msg_destination(msg))) {
|
||||||
msg->sequence = ++adap->sequence;
|
/*
|
||||||
if (!msg->sequence)
|
* If the destination is a logical address our
|
||||||
|
* adapter has already claimed, then just NACK
|
||||||
|
* this. It depends on the hardware what it will
|
||||||
|
* do with a POLL to itself (some OK this), so
|
||||||
|
* it is just as easy to handle it here so the
|
||||||
|
* behavior will be consistent.
|
||||||
|
*/
|
||||||
|
msg->tx_ts = ktime_get_ns();
|
||||||
|
msg->tx_status = CEC_TX_STATUS_NACK |
|
||||||
|
CEC_TX_STATUS_MAX_RETRIES;
|
||||||
|
msg->tx_nack_cnt = 1;
|
||||||
msg->sequence = ++adap->sequence;
|
msg->sequence = ++adap->sequence;
|
||||||
return 0;
|
if (!msg->sequence)
|
||||||
|
msg->sequence = ++adap->sequence;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (msg->len > 1 && !cec_msg_is_broadcast(msg) &&
|
||||||
|
cec_has_log_addr(adap, cec_msg_destination(msg))) {
|
||||||
|
dprintk(1, "%s: destination is the adapter itself\n",
|
||||||
|
__func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (msg->len > 1 && adap->is_configured &&
|
||||||
|
!cec_has_log_addr(adap, cec_msg_initiator(msg))) {
|
||||||
|
dprintk(1, "%s: initiator has unknown logical address %d\n",
|
||||||
|
__func__, cec_msg_initiator(msg));
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (!adap->is_configured && !adap->is_configuring &&
|
||||||
|
msg->msg[0] != 0xf0) {
|
||||||
|
dprintk(1, "%s: adapter is unconfigured\n", __func__);
|
||||||
|
return -ENONET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (msg->len > 1 && !cec_msg_is_broadcast(msg) &&
|
|
||||||
cec_has_log_addr(adap, cec_msg_destination(msg))) {
|
|
||||||
dprintk(1, "%s: destination is the adapter itself\n", __func__);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
if (msg->len > 1 && adap->is_configured &&
|
|
||||||
!cec_has_log_addr(adap, cec_msg_initiator(msg))) {
|
|
||||||
dprintk(1, "%s: initiator has unknown logical address %d\n",
|
|
||||||
__func__, cec_msg_initiator(msg));
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
if (!adap->is_configured && !adap->is_configuring) {
|
if (!adap->is_configured && !adap->is_configuring) {
|
||||||
if (adap->needs_hpd || msg->msg[0] != 0xf0) {
|
if (adap->needs_hpd) {
|
||||||
dprintk(1, "%s: adapter is unconfigured\n", __func__);
|
dprintk(1, "%s: adapter is unconfigured and needs HPD\n",
|
||||||
|
__func__);
|
||||||
return -ENONET;
|
return -ENONET;
|
||||||
}
|
}
|
||||||
if (msg->reply) {
|
if (msg->reply) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user