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

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
Loading
Loading
Loading
Loading
+62 −45
Original line number Diff line number Diff line
@@ -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_data *data;
	bool is_raw = msg_is_raw(msg);

	msg->rx_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. */
		msg->timeout = 1000;
	}
	if (msg->timeout)
		msg->flags &= CEC_MSG_FL_REPLY_TO_FOLLOWERS;
	else
		msg->flags = 0;
	msg->flags &= CEC_MSG_FL_REPLY_TO_FOLLOWERS | CEC_MSG_FL_RAW;

	if (!msg->timeout)
		msg->flags &= ~CEC_MSG_FL_REPLY_TO_FOLLOWERS;

	/* Sanity checks */
	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,
		return -EINVAL;
	}

	if (is_raw) {
		if (!capable(CAP_SYS_RAWIO))
			return -EPERM;
	} else {
		/* A CDC-Only device can only send CDC messages */
		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;
		}

		if (msg->len >= 4 && msg->msg[1] == CEC_MSG_CDC_MESSAGE) {
			msg->msg[2] = adap->phys_addr >> 8;
@@ -773,17 +780,18 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,

		if (msg->len == 1) {
			if (cec_msg_destination(msg) == 0xf) {
			dprintk(1, "%s: invalid poll message\n", __func__);
				dprintk(1, "%s: invalid poll message\n",
					__func__);
				return -EINVAL;
			}
			if (cec_has_log_addr(adap, cec_msg_destination(msg))) {
				/*
			 * 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.
				 * 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 |
@@ -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) &&
		    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;
		}
		if (msg->len > 1 && adap->is_configured &&
@@ -806,11 +815,19 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
				__func__, cec_msg_initiator(msg));
			return -EINVAL;
		}
	if (!adap->is_configured && !adap->is_configuring) {
		if (adap->needs_hpd || msg->msg[0] != 0xf0) {
		if (!adap->is_configured && !adap->is_configuring &&
		    msg->msg[0] != 0xf0) {
			dprintk(1, "%s: adapter is unconfigured\n", __func__);
			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) {
			dprintk(1, "%s: invalid msg->reply\n", __func__);
			return -EINVAL;