Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The user needs to provide enough space for all the data being copied out. Ideally he'll tell you how much space he provided, and you check that everything fits.</p> <p>The copied-out data should (in general) not include any pointers, since they're "local" to a different "process" (the kernel can be viewed as a separate process, as it were, and kernel / user interactions involve process-to-process IPC, similar to sending stuff over local or even Internet-connected sockets).</p> <p>Since the kernel has pretty intimate knowledge of a process, you can skirt these rules somewhat, e.g., you could compute what the user's pointer will be, and copy out a copy of the original data, with the pointer modified appropriately. But that's kind of wasteful. Or, you can copy a kernel pointer and just not use it in the user code, but now you're "leaking data" that "bad guys" can sometimes leverage in various ways. In security-people-speak you've left a wide-open "covert channel".</p> <p>In the end, then, the "right" way to do this tends to be something like this:</p> <pre><code>struct user_interface_version_of_struct { int property; int count; int data[]; /* of size "count" */ }; </code></pre> <p>The user code <code>malloc</code>s (or otherwise arranges to have sufficient space) the "user interface version" and makes some system call to the kernel (<code>read</code>, <code>receive</code>, <code>rcvmsg</code>, <code>ioctl</code>, whatever, as long as it involves doing a "read"-type operation) and tells the kernel: "here's the memory holding the struct, and here's how big it is" (in bytes, or the maximum <code>count</code> value, or whatever: user and kernel simply need to agree on the protocol). The kernel-side code then verifies the user's values in some appropriate manner, and either does the copy-out however is most convenient, or returns an error.</p> <p>"Most convenient" is sometimes two separate copy ops, or some <code>put_user</code> calls, e.g., if the kernel side has the data structure you showed, you might do:</p> <pre><code>/* let's say ulen is the user supplied length in bytes, and uaddr is the user-supplied address */ struct user_interface_version_of_struct *p; needed = sizeof(*p) + 3 * sizeof(int); if (needed &gt; ulen) return -ENOMEM; /* user did not supply enough space */ p = uaddr; error = put_user(1024, &amp;p-&gt;property); if (error == 0) error = put_user(3, &amp;p-&gt;count); if (error == 0 &amp;&amp; copy_to_user(&amp;p-&gt;data, localArray, 3 * sizeof(int)) error = -EFAULT; </code></pre> <p>You may have a situation where you must conform to some not-very-nice interface, though.</p> <hr> <p>Edit: if you're adding your own system call (rather than tying in to <code>read</code> or <code>ioctl</code> for instance), you can separate the header and data, as in <a href="https://stackoverflow.com/a/18520855/1256452">Adam Rosenfield's answer</a>.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload