All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vadim Fedorenko <vadim.fedorenko@linux.dev>
To: Sagi Maimon <maimon.sagi@gmail.com>,
	jonathan.lemon@gmail.com, richardcochran@gmail.com,
	andrew+netdev@lunn.ch, davem@davemloft.net, edumazet@google.com,
	kuba@kernel.org, pabeni@redhat.com
Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org
Subject: Re: [PATCH v4] ptp: ocp: Limit signal/freq counts in show/store functions
Date: Tue, 13 May 2025 20:53:37 +0100	[thread overview]
Message-ID: <4ef4472b-62a5-43f6-bd16-d6e0ace2335a@linux.dev> (raw)
In-Reply-To: <20250511154235.101780-1-maimon.sagi@gmail.com>

On 11.05.2025 16:42, Sagi Maimon wrote:
> The sysfs show/store operations could access uninitialized elements
> in the freq_in[] and signal_out[] arrays, leading to NULL pointer
> dereferences. This patch introduces u8 fields (nr_freq_in,
> nr_signal_out) to track the number of initialized elements, capping
> the maximum at 4 for each array. The show/store functions are updated
> to respect these limits, preventing out-of-bounds access and ensuring
> safe array handling.
> 
> Signed-off-by: Sagi Maimon <maimon.sagi@gmail.com>
> ---
> Addressed comments from Vadim Fedorenko:
>   - https://www.spinics.net/lists/netdev/msg1090730.html
> Changes since v3:
>   - in signal/freq show routine put constant string "UNSUPPORTED" in
>     output instead of returning error.
> ---
> ---
>   drivers/ptp/ptp_ocp.c | 40 +++++++++++++++++++++++++++++++++-------
>   1 file changed, 33 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
> index 2ccdca4f6960..14b4b3bebccd 100644
> --- a/drivers/ptp/ptp_ocp.c
> +++ b/drivers/ptp/ptp_ocp.c
> @@ -315,6 +315,8 @@ struct ptp_ocp_serial_port {
>   #define OCP_BOARD_ID_LEN		13
>   #define OCP_SERIAL_LEN			6
>   #define OCP_SMA_NUM			4
> +#define OCP_SIGNAL_NUM			4
> +#define OCP_FREQ_NUM			4
>   
>   enum {
>   	PORT_GNSS,
> @@ -342,8 +344,8 @@ struct ptp_ocp {
>   	struct dcf_master_reg	__iomem *dcf_out;
>   	struct dcf_slave_reg	__iomem *dcf_in;
>   	struct tod_reg		__iomem *nmea_out;
> -	struct frequency_reg	__iomem *freq_in[4];
> -	struct ptp_ocp_ext_src	*signal_out[4];
> +	struct frequency_reg	__iomem *freq_in[OCP_FREQ_NUM];
> +	struct ptp_ocp_ext_src	*signal_out[OCP_SIGNAL_NUM];
>   	struct ptp_ocp_ext_src	*pps;
>   	struct ptp_ocp_ext_src	*ts0;
>   	struct ptp_ocp_ext_src	*ts1;
> @@ -378,10 +380,12 @@ struct ptp_ocp {
>   	u32			utc_tai_offset;
>   	u32			ts_window_adjust;
>   	u64			fw_cap;
> -	struct ptp_ocp_signal	signal[4];
> +	struct ptp_ocp_signal	signal[OCP_SIGNAL_NUM];
>   	struct ptp_ocp_sma_connector sma[OCP_SMA_NUM];
>   	const struct ocp_sma_op *sma_op;
>   	struct dpll_device *dpll;
> +	int signals_nr;
> +	int freq_in_nr;
>   };
>   
>   #define OCP_REQ_TIMESTAMP	BIT(0)
> @@ -2697,6 +2701,8 @@ ptp_ocp_fb_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
>   	bp->eeprom_map = fb_eeprom_map;
>   	bp->fw_version = ioread32(&bp->image->version);
>   	bp->sma_op = &ocp_fb_sma_op;
> +	bp->signals_nr = 4;
> +	bp->freq_in_nr = 4;
>   
>   	ptp_ocp_fb_set_version(bp);
>   
> @@ -2862,6 +2868,8 @@ ptp_ocp_art_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
>   	bp->fw_version = ioread32(&bp->reg->version);
>   	bp->fw_tag = 2;
>   	bp->sma_op = &ocp_art_sma_op;
> +	bp->signals_nr = 4;
> +	bp->freq_in_nr = 4;
>   
>   	/* Enable MAC serial port during initialisation */
>   	iowrite32(1, &bp->board_config->mro50_serial_activate);
> @@ -2888,6 +2896,8 @@ ptp_ocp_adva_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
>   	bp->flash_start = 0xA00000;
>   	bp->eeprom_map = fb_eeprom_map;
>   	bp->sma_op = &ocp_adva_sma_op;
> +	bp->signals_nr = 2;
> +	bp->freq_in_nr = 2;
>   
>   	version = ioread32(&bp->image->version);
>   	/* if lower 16 bits are empty, this is the fw loader. */
> @@ -3190,6 +3200,9 @@ signal_store(struct device *dev, struct device_attribute *attr,
>   	if (!argv)
>   		return -ENOMEM;
>   
> +	if (gen >= bp->signals_nr)
> +		return -EINVAL;
> +
>   	err = -EINVAL;
>   	s.duty = bp->signal[gen].duty;
>   	s.phase = bp->signal[gen].phase;
> @@ -3247,6 +3260,10 @@ signal_show(struct device *dev, struct device_attribute *attr, char *buf)
>   	int i;
>   
>   	i = (uintptr_t)ea->var;
> +
> +	if (i >= bp->signals_nr)
> +		return sysfs_emit(buf, "UNSUPPORTED\n");
> +
>   	signal = &bp->signal[i];

I've checked the code again. Jakub is right, there is no need to modify
singal/seconds/frequency show/set functions. Now I'm not quite sure how is it
possible to reach this functions with unsupported input? You export a specific
set of attributes for your card:

static const struct ocp_attr_group adva_timecard_groups[] = {
	{ .cap = OCP_CAP_BASIC,	    .group = &adva_timecard_group },
	{ .cap = OCP_CAP_BASIC,	    .group = &ptp_ocp_timecard_tty_group },
	{ .cap = OCP_CAP_SIGNAL,    .group = &fb_timecard_signal0_group },
	{ .cap = OCP_CAP_SIGNAL,    .group = &fb_timecard_signal1_group },
	{ .cap = OCP_CAP_FREQ,	    .group = &fb_timecard_freq0_group },
	{ .cap = OCP_CAP_FREQ,	    .group = &fb_timecard_freq1_group },
	{ },
};

It has only freq1, freq2, gen1, gen2 attributes exported to sysfs. How can it
happen that you can change freq3 or gen3?

The only problem I see is in the summary output - that should be addressed with
this patch (well, you've done it already).

>   
>   	count = sysfs_emit(buf, "%llu %d %llu %d", signal->period,
> @@ -3359,6 +3376,9 @@ seconds_store(struct device *dev, struct device_attribute *attr,
>   	u32 val;
>   	int err;
>   
> +	if (idx >= bp->freq_in_nr)
> +		return -EINVAL;
> +
>   	err = kstrtou32(buf, 0, &val);
>   	if (err)
>   		return err;
> @@ -3381,6 +3401,9 @@ seconds_show(struct device *dev, struct device_attribute *attr, char *buf)
>   	int idx = (uintptr_t)ea->var;
>   	u32 val;
>   
> +	if (idx >= bp->freq_in_nr)
> +		return sysfs_emit(buf, "UNSUPPORTED\n");
> +
>   	val = ioread32(&bp->freq_in[idx]->ctrl);
>   	if (val & 1)
>   		val = (val >> 8) & 0xff;
> @@ -3402,6 +3425,9 @@ frequency_show(struct device *dev, struct device_attribute *attr, char *buf)
>   	int idx = (uintptr_t)ea->var;
>   	u32 val;
>   
> +	if (idx >= bp->freq_in_nr)
> +		return -EINVAL;
> +
>   	val = ioread32(&bp->freq_in[idx]->status);
>   	if (val & FREQ_STATUS_ERROR)
>   		return sysfs_emit(buf, "error\n");
> @@ -4008,7 +4034,7 @@ _signal_summary_show(struct seq_file *s, struct ptp_ocp *bp, int nr)
>   {
>   	struct signal_reg __iomem *reg = bp->signal_out[nr]->mem;
>   	struct ptp_ocp_signal *signal = &bp->signal[nr];
> -	char label[8];
> +	char label[16];
>   	bool on;
>   	u32 val;
>   
> @@ -4031,7 +4057,7 @@ static void
>   _frequency_summary_show(struct seq_file *s, int nr,
>   			struct frequency_reg __iomem *reg)
>   {
> -	char label[8];
> +	char label[16];
>   	bool on;
>   	u32 val;
>   
> @@ -4175,11 +4201,11 @@ ptp_ocp_summary_show(struct seq_file *s, void *data)
>   	}
>   
>   	if (bp->fw_cap & OCP_CAP_SIGNAL)
> -		for (i = 0; i < 4; i++)
> +		for (i = 0; i < bp->signals_nr; i++)
>   			_signal_summary_show(s, bp, i);
>   
>   	if (bp->fw_cap & OCP_CAP_FREQ)
> -		for (i = 0; i < 4; i++)
> +		for (i = 0; i < bp->freq_in_nr; i++)
>   			_frequency_summary_show(s, i, bp->freq_in[i]);
>   
>   	if (bp->irig_out) {

---
pw-bot:cr

  parent reply	other threads:[~2025-05-13 19:53 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-11 15:42 [PATCH v4] ptp: ocp: Limit signal/freq counts in show/store functions Sagi Maimon
2025-05-11 21:16 ` Vadim Fedorenko
2025-05-13 19:53 ` Vadim Fedorenko [this message]
2025-05-14  6:01   ` Sagi Maimon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4ef4472b-62a5-43f6-bd16-d6e0ace2335a@linux.dev \
    --to=vadim.fedorenko@linux.dev \
    --cc=andrew+netdev@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=jonathan.lemon@gmail.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maimon.sagi@gmail.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=richardcochran@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.