0

It is known that it is a good practice to pass arguments (specially if they are of big size like structures) to functions by reference. And to apply the principle of "least privilege", if that function is not supposed to change the values of these passed variables then we need to pass their references as a pointer to constant. My question is, passing as a pointer to constant can not prevent changing the values within the function (You may consider the attached code), so how can we prevent such practice?

void print(const int *ptr) {
    printf("%d\n", *ptr);
    int * p = ptr;
    *p = 11;
}

I am not discussing here whether we can change the value of a constant through pointers or not. I know that we can. But my question is how to prevent such practice to enforce the principle of least privilege? otherwise what is the use of passing a reference as a pointer to constant if we can play around it easily as shown in the code above

MKSOI
  • 49
  • 5
  • Possible duplicate of [Can we change the value of a constant through pointers?](http://stackoverflow.com/questions/3801557/can-we-change-the-value-of-a-constant-through-pointers) – Jcl Mar 11 '16 at 09:36
  • You have not defined *p as constant! – Linus Mar 11 '16 at 09:36
  • 3
    Neither does passing by constant reference, because you can always cast away the constness. – jotik Mar 11 '16 at 09:38
  • 2
    You can't prevent it in C. Functions can always cast pointers to strip off any `const` restrictions. – Tom Karzes Mar 11 '16 at 09:38
  • Thanks for your comments. The topic is not duplicate because I am not discussing here whether we can change the value of a constant through pointers or not. I know that we can. But my question is how to prevent such practice to enforce the principle of least privilege? otherwise what is the use of passing a reference as a pointer to constant if we can play around it easily as shown in the code? – MKSOI Mar 11 '16 at 09:52

3 Answers3

1

Since C is unmanaged, there's not really anything you can do to prevent a locally called C function from messing up stuff outside itself. Even if the language enforced "const-ness" somehow, there'd by many other things that print() could do, if it were so inclined, that would violate least privilege.

Instead C provides ways to cooperatively implement safer programs. In this case print() has to cooperate by declaring p as a pointer to a const int.

As a point of comparison: from a security perspective, a C caller and a C function are within the same trust boundary. Specifically they are within the same process (thus excluding calls across trust boundaries, like IPCs or RPC, from this discussion). Within a given trust boundary all actors (almost) always have the same set of privileges. "Privilege" here meaning an externally granted right to perform an action as opposed to self imposed restrictions.

Actors within the same trust boundary are "free" to tamper with each other. If function A tampers with caller B, there's no greater threat than if B acted on its own. B can do the same things whether acting on its own or whether caused to do something by A. From a security perspective A and B are equally privileged.

So it might be more helpful to think of "principal of least self-allowed action" rather than "principal of least privilege" in the case of C callers/functions.

Χpẘ
  • 3,403
  • 1
  • 13
  • 22
  • Thanks for your comment. My point is that the function and the caller function might have been written using different programmers and I want to ensure for the programmer that if a function, declared in a particular library, that it is not going to change the value of an argument because it is pointed out by a pointer to constant, then it is guaranteed not to do so and there is no way around that. – MKSOI Mar 11 '16 at 13:05
  • By including a library in your executable you are implicitly extending trust to the library. So your primary option is to vet the library and the library writer (or not use the library). Once you've accepted the library as trustworthy (enough) it then becomes one of the cooperating actors. There is nothing an unmanaged language like C can do to provide the hard enforcement of privilege you seem to be looking for. – Χpẘ Mar 11 '16 at 21:24
1

This code int * p = ptr; is ill-formed, it is not valid C.

According to the rules of simple assignment (6.5.16.1), emphasis mine:

One of the following shall hold:

/--/

  • the left operand has atomic, qualified, or unqualified pointer type, and (considering the type the left operand would have after lvalue conversion) both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right;

Qualifiers means type qualifiers, such as const or volatile. The left operand in your code doesn't have the same qualifiers as the right operand, so it should not compile.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Thanks for your comment. But it is compiling and also running in VS! – MKSOI Mar 11 '16 at 12:58
  • @user3480226 VS is not a standard compliant C compiler, that's why. File a bug report to Microsoft, I'm sure they'll fix it. – Lundin Mar 11 '16 at 13:03
  • I tried it with GCC on linux it gave a warning. Then I have typecasted like {int * p = (int *) ptr} it gave no warning. My point is that if we have two programmers, one writes the function code while the other one just uses it. C should has a mechanism that can ensure to the using programmer that his/her passed arguments are not going to be altered within the function as declared by the function's signature and that the function programmer has no way to play around. – MKSOI Mar 14 '16 at 10:21
  • @user3480226 If you set GCC up to properly compile against standard C `-std=c11 -pedantic-errors`, you'll get an error. But of course, if you explicitly cast away the cost qualifier, C allows it. That's very bad practice though, a function doing that to `const` parameters can only be regarded as broken. The C language is designed with the assumption that you won't be doing really dumb things, though you always have the option explicitly tell it "I want to do really dumb things!" and it will let you. – Lundin Mar 14 '16 at 10:34
  • Given user3480226's reference to "least privilege", I don't think he's worried about someone doing "dumb things" but about the author of a called function doing things that the author of the calling code wants to prevent - in effect put the called code into a sandbox. But that kind of fencing is not in C's bag of tricks. Which means the authors have to cooperate: the called code's author has to respect the function's prototype or else, as you said, be considered broken. – Χpẘ Mar 15 '16 at 01:44
  • @Χpẘ If the author of the function declared parameters as const, then cast away the const qualifier, the author of the function is doing really dumb things, period. In which case there is nothing the caller can do to protect themselves, except for only using code written by competent professionals. – Lundin Mar 15 '16 at 07:14
  • Or the author may be doing really clever things - since we don't know the intent, skill, or motivation of that author. – Χpẘ Mar 15 '16 at 15:59
0

As "Functions can always cast pointers to strip off any const restrictions" (see comment by jotik), you cannot prevent it by ways of the language.

What remains is to write it down in your company's coding standard and explicitly include it in code reviews to spot where a programmer still does it.

When such use is spotted, then the reason could be investigated. Maybe the programmer is right and the function signature should be changed (or a new function introduced).

Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41