The least surprising way to pass arrays in C++ is by reference:
void foo(int (&mask)[3][3]);
Your first try
void foo(int mask[3][3])
should have worked, but it would be internally converted to
void foo(int (*mask)[3])
with unexpected implications for sizeof and other things that need a "real" array.
Your other idea int** doesn't work, because a 2-D dimensional array is not the same as an array of pointers, even though the a[i][j] notation works equally well for both.
If you don't want to share the content with the function (and see changes it might make), then none of the above will help. Passing a pointer by value still shares the target object. In that case you need to put the array inside another object, for example a std::array<std::array<int,3>,3>