Merge tag 'selinux-pr-20210629' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / arch / x86 / lib / insn-eval.c
index a67afd74232c6526ed45951ffbd32bb8e0db6e51..a1d24fdc07cf0280ab33cabe0e573f4795049820 100644 (file)
@@ -1417,7 +1417,7 @@ void __user *insn_get_addr_ref(struct insn *insn, struct pt_regs *regs)
        }
 }
 
-static unsigned long insn_get_effective_ip(struct pt_regs *regs)
+static int insn_get_effective_ip(struct pt_regs *regs, unsigned long *ip)
 {
        unsigned long seg_base = 0;
 
@@ -1430,10 +1430,12 @@ static unsigned long insn_get_effective_ip(struct pt_regs *regs)
        if (!user_64bit_mode(regs)) {
                seg_base = insn_get_seg_base(regs, INAT_SEG_REG_CS);
                if (seg_base == -1L)
-                       return 0;
+                       return -EINVAL;
        }
 
-       return seg_base + regs->ip;
+       *ip = seg_base + regs->ip;
+
+       return 0;
 }
 
 /**
@@ -1446,18 +1448,17 @@ static unsigned long insn_get_effective_ip(struct pt_regs *regs)
  *
  * Returns:
  *
- * Number of instruction bytes copied.
- *
- * 0 if nothing was copied.
+ * - number of instruction bytes copied.
+ * - 0 if nothing was copied.
+ * - -EINVAL if the linear address of the instruction could not be calculated
  */
 int insn_fetch_from_user(struct pt_regs *regs, unsigned char buf[MAX_INSN_SIZE])
 {
        unsigned long ip;
        int not_copied;
 
-       ip = insn_get_effective_ip(regs);
-       if (!ip)
-               return 0;
+       if (insn_get_effective_ip(regs, &ip))
+               return -EINVAL;
 
        not_copied = copy_from_user(buf, (void __user *)ip, MAX_INSN_SIZE);
 
@@ -1475,18 +1476,17 @@ int insn_fetch_from_user(struct pt_regs *regs, unsigned char buf[MAX_INSN_SIZE])
  *
  * Returns:
  *
- * Number of instruction bytes copied.
- *
- * 0 if nothing was copied.
+ *  - number of instruction bytes copied.
+ *  - 0 if nothing was copied.
+ *  - -EINVAL if the linear address of the instruction could not be calculated.
  */
 int insn_fetch_from_user_inatomic(struct pt_regs *regs, unsigned char buf[MAX_INSN_SIZE])
 {
        unsigned long ip;
        int not_copied;
 
-       ip = insn_get_effective_ip(regs);
-       if (!ip)
-               return 0;
+       if (insn_get_effective_ip(regs, &ip))
+               return -EINVAL;
 
        not_copied = __copy_from_user_inatomic(buf, (void __user *)ip, MAX_INSN_SIZE);