lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Tue, 2 Jan 2018 08:47:03 +0100
From:   Alexandre Belloni <alexandre.belloni@...e-electrons.com>
To:     Baolin Wang <baolin.wang@...aro.org>
Cc:     a.zummo@...ertech.it, corbet@....net, arnd@...db.de,
        broonie@...nel.org, linux-rtc@...r.kernel.org,
        linux-kernel@...r.kernel.org, linux-doc@...r.kernel.org
Subject: Re: [RFC PATCH 1/4] rtc: Introduce one interface to save the RTC
 hardware time range

Hi Baolin,

Could you have a look at
https://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git/commit/?h=rtc-ranges

My approach has multiple advantages as it works for 64-bit counters and
the range can be updated at runtime.

On 02/01/2018 at 13:10:05 +0800, Baolin Wang wrote:
> In order to the setting time values are not beyond the limitation
> supported by RTC hardware, we introduce one interface to tell the
> hardware range to the RTC core, which are used to valid if the
> setting time values are in the RTC hardware range.
> 
> Moreover we also need the RTC hardware range to expand the RTC
> range in next patches by adding one offset.
> 
> Signed-off-by: Baolin Wang <baolin.wang@...aro.org>
> ---
>  drivers/rtc/class.c     |   13 ++++++++++
>  drivers/rtc/interface.c |   62 +++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/rtc.h     |    9 +++++++
>  3 files changed, 84 insertions(+)
> 
> diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
> index 722d683..31fc0f1 100644
> --- a/drivers/rtc/class.c
> +++ b/drivers/rtc/class.c
> @@ -247,6 +247,12 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
>  
>  	dev_set_name(&rtc->dev, "rtc%d", id);
>  
> +	err = rtc_read_range(rtc, &rtc->max_hw_secs, &rtc->min_hw_secs);
> +	if (err) {
> +		dev_err(&rtc->dev, "%s: failed to get RTC range\n", name);
> +		goto exit_ida;
> +	}
> +
>  	/* Check to see if there is an ALARM already set in hw */
>  	err = __rtc_read_alarm(rtc, &alrm);
>  
> @@ -436,6 +442,13 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc)
>  
>  	rtc->owner = owner;
>  
> +	err = rtc_read_range(rtc, &rtc->max_hw_secs, &rtc->min_hw_secs);
> +	if (err) {
> +		dev_err(&rtc->dev, "%s: failed to get RTC range\n",
> +			dev_name(&rtc->dev));
> +		return err;
> +	}
> +
>  	/* Check to see if there is an ALARM already set in hw */
>  	err = __rtc_read_alarm(rtc, &alrm);
>  	if (!err && !rtc_valid_tm(&alrm.time))
> diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
> index 672b192..c8090e3 100644
> --- a/drivers/rtc/interface.c
> +++ b/drivers/rtc/interface.c
> @@ -65,6 +65,10 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
>  	if (err != 0)
>  		return err;
>  
> +	err = rtc_valid_range(rtc, tm);
> +	if (err)
> +		return err;
> +
>  	err = mutex_lock_interruptible(&rtc->ops_lock);
>  	if (err)
>  		return err;
> @@ -329,6 +333,11 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
>  	err = rtc_valid_tm(&alarm->time);
>  	if (err)
>  		return err;
> +
> +	err = rtc_valid_range(rtc, &alarm->time);
> +	if (err)
> +		return err;
> +
>  	scheduled = rtc_tm_to_time64(&alarm->time);
>  
>  	/* Make sure we're not setting alarms in the past */
> @@ -1027,3 +1036,56 @@ int rtc_set_offset(struct rtc_device *rtc, long offset)
>  	mutex_unlock(&rtc->ops_lock);
>  	return ret;
>  }
> +
> +/* rtc_read_range - Read the max and min hardware count supported by RTC device
> + * @ rtc: rtc device to be used.
> + * @ max_hw_secs: maximum hardware count in seconds, which can represent
> + * the maximum time values in RTC hardware.
> + * @ min_hw_secs: minimum hardware count in seconds, which can represent
> + * the minimum time values in RTC hardware.
> + *
> + * The max_hw_secs and min_hw_secs implemented by user must represent the
> + * correct hardware start time and maximum time, which means the count
> + * will wrap around to min_hw_secs after the maximum count.
> + *
> + * If user did not implement the read_range() interface, we can set max_hw_secs
> + * and min_hw_secs to 0, which avoids validing the range.
> + */
> +int rtc_read_range(struct rtc_device *rtc, time64_t *max_hw_secs,
> +		   time64_t *min_hw_secs)
> +{
> +	int ret;
> +
> +	if (!rtc->ops || !rtc->ops->read_range) {
> +		*max_hw_secs = 0;
> +		*min_hw_secs = 0;
> +		return 0;
> +	}
> +
> +	mutex_lock(&rtc->ops_lock);
> +	ret = rtc->ops->read_range(rtc->dev.parent, max_hw_secs, min_hw_secs);
> +	mutex_unlock(&rtc->ops_lock);
> +
> +	return ret;
> +}
> +
> +/* rtc_valid_range - Valid if the setting time in the RTC range
> + * @ rtc: rtc device to be used.
> + * @ tm: time values need to valid.
> + *
> + * Only the rtc->max_hw_secs was set, then we can valid if the setting time
> + * values are beyond the RTC range.
> + */
> +int rtc_valid_range(struct rtc_device *rtc, struct rtc_time *tm)
> +{
> +	time64_t secs;
> +
> +	if (!rtc->max_hw_secs)
> +		return 0;
> +
> +	secs = rtc_tm_to_time64(tm);
> +	if (secs < rtc->min_hw_secs || secs > rtc->max_hw_secs)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> diff --git a/include/linux/rtc.h b/include/linux/rtc.h
> index 41319a2..19a8989 100644
> --- a/include/linux/rtc.h
> +++ b/include/linux/rtc.h
> @@ -85,6 +85,8 @@ struct rtc_class_ops {
>  	int (*alarm_irq_enable)(struct device *, unsigned int enabled);
>  	int (*read_offset)(struct device *, long *offset);
>  	int (*set_offset)(struct device *, long offset);
> +	int (*read_range)(struct device *, time64_t *max_hw_secs,
> +			  time64_t *min_hw_secs);
>  };
>  
>  #define RTC_DEVICE_NAME_SIZE 20
> @@ -152,6 +154,9 @@ struct rtc_device {
>  	bool nvram_old_abi;
>  	struct bin_attribute *nvram;
>  
> +	time64_t max_hw_secs;
> +	time64_t min_hw_secs;
> +
>  #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
>  	struct work_struct uie_task;
>  	struct timer_list uie_timer;
> @@ -225,6 +230,10 @@ int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer *timer,
>  int rtc_set_offset(struct rtc_device *rtc, long offset);
>  void rtc_timer_do_work(struct work_struct *work);
>  
> +int rtc_read_range(struct rtc_device *rtc, time64_t *max_hw_secs,
> +		   time64_t *min_hw_secs);
> +int rtc_valid_range(struct rtc_device *rtc, struct rtc_time *tm);
> +
>  static inline bool is_leap_year(unsigned int year)
>  {
>  	return (!(year % 4) && (year % 100)) || !(year % 400);
> -- 
> 1.7.9.5
> 

-- 
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ