All of lore.kernel.org
 help / color / mirror / Atom feed
From: Matt Ranostay <matt.ranostay@konsulko.com>
To: linux-kernel@vger.kernel.org
Cc: Matt Ranostay <matt.ranostay@konsulko.com>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Subject: [PATCH RESEND 2/2] pps: fix padding issue with PPS_FETCH for ioctl_compat
Date: Fri, 10 Mar 2017 15:19:45 -0800	[thread overview]
Message-ID: <20170310231945.16684-3-matt.ranostay@konsulko.com> (raw)
In-Reply-To: <20170310231945.16684-1-matt.ranostay@konsulko.com>

Issue is that x86 32-bit aligns to 4-bytes instead of 8-bytes
so this patchset works around the issue and corrects the data
returned in pps_fdata_compat.

Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: Rodolfo Giometti <giometti@enneenne.com>
Signed-off-by: Matt Ranostay <matt.ranostay@konsulko.com>
---
 drivers/pps/pps.c        | 110 ++++++++++++++++++++++++++++++++++-------------
 include/uapi/linux/pps.h |  19 ++++++++
 2 files changed, 98 insertions(+), 31 deletions(-)

diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c
index 452ead5a5e52..6eb0db37dd88 100644
--- a/drivers/pps/pps.c
+++ b/drivers/pps/pps.c
@@ -64,6 +64,43 @@ static int pps_cdev_fasync(int fd, struct file *file, int on)
 	return fasync_helper(fd, file, on, &pps->async_queue);
 }
 
+static int pps_cdev_pps_fetch(struct pps_device *pps, struct pps_fdata *fdata)
+{
+	unsigned int ev = pps->last_ev;
+	int err = 0;
+
+	/* Manage the timeout */
+	if (fdata->timeout.flags & PPS_TIME_INVALID)
+		err = wait_event_interruptible(pps->queue,
+				ev != pps->last_ev);
+	else {
+		unsigned long ticks;
+
+		dev_dbg(pps->dev, "timeout %lld.%09d\n",
+				(long long) fdata->timeout.sec,
+				fdata->timeout.nsec);
+		ticks = fdata->timeout.sec * HZ;
+		ticks += fdata->timeout.nsec / (NSEC_PER_SEC / HZ);
+
+		if (ticks != 0) {
+			err = wait_event_interruptible_timeout(
+					pps->queue,
+					ev != pps->last_ev,
+					ticks);
+			if (err == 0)
+				return -ETIMEDOUT;
+		}
+	}
+
+	/* Check for pending signals */
+	if (err == -ERESTARTSYS) {
+		dev_dbg(pps->dev, "pending signal caught\n");
+		return -EINTR;
+	}
+
+	return 0;
+}
+
 static long pps_cdev_ioctl(struct file *file,
 		unsigned int cmd, unsigned long arg)
 {
@@ -144,7 +181,6 @@ static long pps_cdev_ioctl(struct file *file,
 
 	case PPS_FETCH: {
 		struct pps_fdata fdata;
-		unsigned int ev;
 
 		dev_dbg(pps->dev, "PPS_FETCH\n");
 
@@ -152,36 +188,9 @@ static long pps_cdev_ioctl(struct file *file,
 		if (err)
 			return -EFAULT;
 
-		ev = pps->last_ev;
-
-		/* Manage the timeout */
-		if (fdata.timeout.flags & PPS_TIME_INVALID)
-			err = wait_event_interruptible(pps->queue,
-					ev != pps->last_ev);
-		else {
-			unsigned long ticks;
-
-			dev_dbg(pps->dev, "timeout %lld.%09d\n",
-					(long long) fdata.timeout.sec,
-					fdata.timeout.nsec);
-			ticks = fdata.timeout.sec * HZ;
-			ticks += fdata.timeout.nsec / (NSEC_PER_SEC / HZ);
-
-			if (ticks != 0) {
-				err = wait_event_interruptible_timeout(
-						pps->queue,
-						ev != pps->last_ev,
-						ticks);
-				if (err == 0)
-					return -ETIMEDOUT;
-			}
-		}
-
-		/* Check for pending signals */
-		if (err == -ERESTARTSYS) {
-			dev_dbg(pps->dev, "pending signal caught\n");
-			return -EINTR;
-		}
+		err = pps_cdev_pps_fetch(pps, &fdata);
+		if (err)
+			return err;
 
 		/* Return the fetched timestamp */
 		spin_lock_irq(&pps->lock);
@@ -246,8 +255,47 @@ static long pps_cdev_ioctl(struct file *file,
 static long pps_cdev_compat_ioctl(struct file *file,
 		unsigned int cmd, unsigned long arg)
 {
+	struct pps_device *pps = file->private_data;
+	void __user *uarg = (void __user *) arg;
+
 	cmd = _IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(void *));
 
+	if (cmd == PPS_FETCH) {
+		struct pps_fdata_compat compat;
+		struct pps_fdata fdata;
+		int err;
+
+		dev_dbg(pps->dev, "PPS_FETCH\n");
+
+		err = copy_from_user(&compat, uarg, sizeof(struct pps_fdata_compat));
+		if (err)
+			return -EFAULT;
+
+		memcpy(&fdata.timeout, &compat.timeout,
+					sizeof(struct pps_ktime_compat));
+
+		err = pps_cdev_pps_fetch(pps, &fdata);
+		if (err)
+			return err;
+
+		/* Return the fetched timestamp */
+		spin_lock_irq(&pps->lock);
+
+		compat.info.assert_sequence = pps->assert_sequence;
+		compat.info.clear_sequence = pps->clear_sequence;
+		compat.info.current_mode = pps->current_mode;
+
+		memcpy(&compat.info.assert_tu, &pps->assert_tu,
+				sizeof(struct pps_ktime_compat));
+		memcpy(&compat.info.clear_tu, &pps->clear_tu,
+				sizeof(struct pps_ktime_compat));
+
+		spin_unlock_irq(&pps->lock);
+
+		return copy_to_user(uarg, &compat,
+				sizeof(struct pps_fdata_compat)) ? -EFAULT : 0;
+	}
+
 	return pps_cdev_ioctl(file, cmd, arg);
 }
 #else
diff --git a/include/uapi/linux/pps.h b/include/uapi/linux/pps.h
index a9bb1d93451a..c1cb3825a8bc 100644
--- a/include/uapi/linux/pps.h
+++ b/include/uapi/linux/pps.h
@@ -55,6 +55,12 @@ struct pps_ktime {
 	__s32 nsec;
 	__u32 flags;
 };
+
+struct pps_ktime_compat {
+	__s64 sec;
+	__s32 nsec;
+	__u32 flags;
+} __attribute__((packed, aligned(4)));
 #define PPS_TIME_INVALID	(1<<0)	/* used to specify timeout==NULL */
 
 struct pps_kinfo {
@@ -65,6 +71,14 @@ struct pps_kinfo {
 	int current_mode;		/* current mode bits */
 };
 
+struct pps_kinfo_compat {
+	__u32 assert_sequence;			/* seq. num. of assert event */
+	__u32 clear_sequence;			/* seq. num. of clear event */
+	struct pps_ktime_compat assert_tu;	/* time of assert event */
+	struct pps_ktime_compat clear_tu;	/* time of clear event */
+	int current_mode;			/* current mode bits */
+};
+
 struct pps_kparams {
 	int api_version;		/* API version # */
 	int mode;			/* mode bits */
@@ -114,6 +128,11 @@ struct pps_fdata {
 	struct pps_ktime timeout;
 };
 
+struct pps_fdata_compat {
+	struct pps_kinfo_compat info;
+	struct pps_ktime_compat timeout;
+};
+
 struct pps_bind_args {
 	int tsformat;	/* format of time stamps */
 	int edge;	/* selected event type */
-- 
2.10.2

      parent reply	other threads:[~2017-03-10 23:21 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-10 23:19 [PATCH RESEND 0/2] pps: add ioctl_compat support Matt Ranostay
2017-03-10 23:19 ` [PATCH RESEND 1/2] pps: add ioctl_compat function to correct ioctl definitions Matt Ranostay
2017-03-10 23:19 ` Matt Ranostay [this message]

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=20170310231945.16684-3-matt.ranostay@konsulko.com \
    --to=matt.ranostay@konsulko.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    /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.